MCPcopy
hub / github.com/vercel/next.js / Script

Function Script

packages/next/src/client/script.tsx:200–380  ·  view source on GitHub ↗

* Load a third-party scripts in an optimized way. * * Read more: [Next.js Docs: `next/script`](https://nextjs.org/docs/app/api-reference/components/script)

(props: ScriptProps)

Source from the content-addressed store, hash-verified

198 * Read more: [Next.js Docs: `next/script`](https://nextjs.org/docs/app/api-reference/components/script)
199 */
200function Script(props: ScriptProps): JSX.Element | null {
201 const {
202 id,
203 src = '',
204 onLoad = () => {},
205 onReady = null,
206 strategy = 'afterInteractive',
207 onError,
208 stylesheets,
209 ...restProps
210 } = props
211
212 // Context is available only during SSR
213 let { updateScripts, scripts, getIsSsr, appDir, nonce } =
214 useContext(HeadManagerContext)
215
216 // if a nonce is explicitly passed to the script tag, favor that over the automatic handling
217 nonce = restProps.nonce || nonce
218
219 /**
220 * - First mount:
221 * 1. The useEffect for onReady executes
222 * 2. hasOnReadyEffectCalled.current is false, but the script hasn't loaded yet (not in LoadCache)
223 * onReady is skipped, set hasOnReadyEffectCalled.current to true
224 * 3. The useEffect for loadScript executes
225 * 4. hasLoadScriptEffectCalled.current is false, loadScript executes
226 * Once the script is loaded, the onLoad and onReady will be called by then
227 * [If strict mode is enabled / is wrapped in <OffScreen /> component]
228 * 5. The useEffect for onReady executes again
229 * 6. hasOnReadyEffectCalled.current is true, so entire effect is skipped
230 * 7. The useEffect for loadScript executes again
231 * 8. hasLoadScriptEffectCalled.current is true, so entire effect is skipped
232 *
233 * - Second mount:
234 * 1. The useEffect for onReady executes
235 * 2. hasOnReadyEffectCalled.current is false, but the script has already loaded (found in LoadCache)
236 * onReady is called, set hasOnReadyEffectCalled.current to true
237 * 3. The useEffect for loadScript executes
238 * 4. The script is already loaded, loadScript bails out
239 * [If strict mode is enabled / is wrapped in <OffScreen /> component]
240 * 5. The useEffect for onReady executes again
241 * 6. hasOnReadyEffectCalled.current is true, so entire effect is skipped
242 * 7. The useEffect for loadScript executes again
243 * 8. hasLoadScriptEffectCalled.current is true, so entire effect is skipped
244 */
245 const hasOnReadyEffectCalled = useRef(false)
246
247 useEffect(() => {
248 const cacheKey = id || src
249 if (!hasOnReadyEffectCalled.current) {
250 // Run onReady if script has loaded before but component is re-mounted
251 if (onReady && cacheKey && LoadCache.has(cacheKey)) {
252 onReady()
253 }
254
255 hasOnReadyEffectCalled.current = true
256 }
257 }, [onReady, id, src])

Callers

nothing calls this directly

Calls 8

htmlEscapeJsonStringFunction · 0.90
loadScriptFunction · 0.85
loadLazyScriptFunction · 0.85
hasMethod · 0.45
concatMethod · 0.45
addMethod · 0.45
forEachMethod · 0.45
stringifyMethod · 0.45

Tested by

no test coverage detected