mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
I've added a new page to the Next.js docs about optimizing videos. It covers: - the native video and iframe tag - displaying externally hosted videos (i.e. from youtube) - self hosting strategies and best practices - Video optimization techniques --------- Co-authored-by: Lee Robinson <[email protected]> Co-authored-by: Delba de Oliveira <[email protected]> Co-authored-by: Josh Lubawy <[email protected]> Co-authored-by: Balázs Orbán <[email protected]>
376 lines
10 KiB
Plaintext
376 lines
10 KiB
Plaintext
---
|
|
title: Script Optimization
|
|
nav_title: Scripts
|
|
description: Optimize 3rd party scripts with the built-in Script component.
|
|
related:
|
|
title: API Reference
|
|
description: Learn more about the next/script API.
|
|
links:
|
|
- app/api-reference/components/script
|
|
---
|
|
|
|
{/* The content of this doc is shared between the app and pages router. You can use the `<PagesOnly>Content</PagesOnly>` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}
|
|
|
|
<AppOnly>
|
|
|
|
### Layout Scripts
|
|
|
|
To load a third-party script for multiple routes, import `next/script` and include the script directly in your layout component:
|
|
|
|
```tsx filename="app/dashboard/layout.tsx" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function DashboardLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
return (
|
|
<>
|
|
<section>{children}</section>
|
|
<Script src="https://example.com/script.js" />
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/dashboard/layout.js" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function DashboardLayout({ children }) {
|
|
return (
|
|
<>
|
|
<section>{children}</section>
|
|
<Script src="https://example.com/script.js" />
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
The third-party script is fetched when the folder route (e.g. `dashboard/page.js`) or any nested route (e.g. `dashboard/settings/page.js`) is accessed by the user. Next.js will ensure the script will **only load once**, even if a user navigates between multiple routes in the same layout.
|
|
|
|
</AppOnly>
|
|
|
|
### Application Scripts
|
|
|
|
<AppOnly>
|
|
|
|
To load a third-party script for all routes, import `next/script` and include the script directly in your root layout:
|
|
|
|
```tsx filename="app/layout.tsx" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
return (
|
|
<html lang="en">
|
|
<body>{children}</body>
|
|
<Script src="https://example.com/script.js" />
|
|
</html>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/layout.js" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function RootLayout({ children }) {
|
|
return (
|
|
<html lang="en">
|
|
<body>{children}</body>
|
|
<Script src="https://example.com/script.js" />
|
|
</html>
|
|
)
|
|
}
|
|
```
|
|
|
|
</AppOnly>
|
|
|
|
<PagesOnly>
|
|
|
|
To load a third-party script for all routes, import `next/script` and include the script directly in your custom `_app`:
|
|
|
|
```jsx filename="pages/_app.js"
|
|
import Script from 'next/script'
|
|
|
|
export default function MyApp({ Component, pageProps }) {
|
|
return (
|
|
<>
|
|
<Component {...pageProps} />
|
|
<Script src="https://example.com/script.js" />
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
</PagesOnly>
|
|
|
|
This script will load and execute when _any_ route in your application is accessed. Next.js will ensure the script will **only load once**, even if a user navigates between multiple pages.
|
|
|
|
> **Recommendation**: We recommend only including third-party scripts in specific pages or layouts in order to minimize any unnecessary impact to performance.
|
|
|
|
### Strategy
|
|
|
|
Although the default behavior of `next/script` allows you to load third-party scripts in any page or layout, you can fine-tune its loading behavior by using the `strategy` property:
|
|
|
|
- `beforeInteractive`: Load the script before any Next.js code and before any page hydration occurs.
|
|
- `afterInteractive`: (**default**) Load the script early but after some hydration on the page occurs.
|
|
- `lazyOnload`: Load the script later during browser idle time.
|
|
- `worker`: (experimental) Load the script in a web worker.
|
|
|
|
Refer to the [`next/script`](/docs/app/api-reference/components/script#strategy) API reference documentation to learn more about each strategy and their use cases.
|
|
|
|
### Offloading Scripts To A Web Worker (Experimental)
|
|
|
|
> **Warning:** The `worker` strategy is not yet stable and does not yet work with the [`app`](/docs/app/building-your-application/routing/defining-routes) directory. Use with caution.
|
|
|
|
Scripts that use the `worker` strategy are offloaded and executed in a web worker with [Partytown](https://partytown.builder.io/). This can improve the performance of your site by dedicating the main thread to the rest of your application code.
|
|
|
|
This strategy is still experimental and can only be used if the `nextScriptWorkers` flag is enabled in `next.config.js`:
|
|
|
|
```js filename="next.config.js"
|
|
module.exports = {
|
|
experimental: {
|
|
nextScriptWorkers: true,
|
|
},
|
|
}
|
|
```
|
|
|
|
Then, run `next` (normally `npm run dev` or `yarn dev`) and Next.js will guide you through the installation of the required packages to finish the setup:
|
|
|
|
```bash filename="Terminal"
|
|
npm run dev
|
|
```
|
|
|
|
You'll see instructions like these: Please install Partytown by running `npm install @builder.io/partytown`
|
|
|
|
Once setup is complete, defining `strategy="worker"` will automatically instantiate Partytown in your application and offload the script to a web worker.
|
|
|
|
```tsx filename="pages/home.tsx" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Home() {
|
|
return (
|
|
<>
|
|
<Script src="https://example.com/script.js" strategy="worker" />
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="pages/home.js" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Home() {
|
|
return (
|
|
<>
|
|
<Script src="https://example.com/script.js" strategy="worker" />
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
There are a number of trade-offs that need to be considered when loading a third-party script in a web worker. Please see Partytown's [tradeoffs](https://partytown.builder.io/trade-offs) documentation for more information.
|
|
|
|
### Inline Scripts
|
|
|
|
Inline scripts, or scripts not loaded from an external file, are also supported by the Script component. They can be written by placing the JavaScript within curly braces:
|
|
|
|
```jsx
|
|
<Script id="show-banner">
|
|
{`document.getElementById('banner').classList.remove('hidden')`}
|
|
</Script>
|
|
```
|
|
|
|
Or by using the `dangerouslySetInnerHTML` property:
|
|
|
|
```jsx
|
|
<Script
|
|
id="show-banner"
|
|
dangerouslySetInnerHTML={{
|
|
__html: `document.getElementById('banner').classList.remove('hidden')`,
|
|
}}
|
|
/>
|
|
```
|
|
|
|
> **Warning**: An `id` property must be assigned for inline scripts in order for Next.js to track and optimize the script.
|
|
|
|
### Executing Additional Code
|
|
|
|
Event handlers can be used with the Script component to execute additional code after a certain event occurs:
|
|
|
|
- `onLoad`: Execute code after the script has finished loading.
|
|
- `onReady`: Execute code after the script has finished loading and every time the component is mounted.
|
|
- `onError`: Execute code if the script fails to load.
|
|
|
|
<AppOnly>
|
|
|
|
These handlers will only work when `next/script` is imported and used inside of a [Client Component](/docs/app/building-your-application/rendering/client-components) where `"use client"` is defined as the first line of code:
|
|
|
|
```tsx filename="app/page.tsx" switcher
|
|
'use client'
|
|
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
onLoad={() => {
|
|
console.log('Script has loaded')
|
|
}}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/page.js" switcher
|
|
'use client'
|
|
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
onLoad={() => {
|
|
console.log('Script has loaded')
|
|
}}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
Refer to the [`next/script`](/docs/app/api-reference/components/script#onload) API reference to learn more about each event handler and view examples.
|
|
|
|
</AppOnly>
|
|
|
|
<PagesOnly>
|
|
|
|
These handlers will only work when `next/script` is imported and used inside of a [Client Component](/docs/app/building-your-application/rendering/client-components) where `"use client"` is defined as the first line of code:
|
|
|
|
```tsx filename="pages/index.tsx" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
onLoad={() => {
|
|
console.log('Script has loaded')
|
|
}}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="pages/index.js" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
onLoad={() => {
|
|
console.log('Script has loaded')
|
|
}}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
Refer to the [`next/script`](/docs/pages/api-reference/components/script#onload) API reference to learn more about each event handler and view examples.
|
|
|
|
</PagesOnly>
|
|
|
|
### Additional Attributes
|
|
|
|
There are many DOM attributes that can be assigned to a `<script>` element that are not used by the Script component, like [`nonce`](https://developer.mozilla.org/docs/Web/HTML/Global_attributes/nonce) or [custom data attributes](https://developer.mozilla.org/docs/Web/HTML/Global_attributes/data-*). Including any additional attributes will automatically forward it to the final, optimized `<script>` element that is included in the HTML.
|
|
|
|
<AppOnly>
|
|
|
|
```tsx filename="app/page.tsx" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
id="example-script"
|
|
nonce="XUENAJFW"
|
|
data-test="script"
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/page.js" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
id="example-script"
|
|
nonce="XUENAJFW"
|
|
data-test="script"
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
</AppOnly>
|
|
|
|
<PagesOnly>
|
|
|
|
```tsx filename="pages/index.tsx" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
id="example-script"
|
|
nonce="XUENAJFW"
|
|
data-test="script"
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="pages/index.js" switcher
|
|
import Script from 'next/script'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<Script
|
|
src="https://example.com/script.js"
|
|
id="example-script"
|
|
nonce="XUENAJFW"
|
|
data-test="script"
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
```
|
|
|
|
</PagesOnly>
|