Skip to content

Commit

Permalink
Improve the next/script documentation. (#26325)
Browse files Browse the repository at this point in the history
* Improve the `next/script` documentation.

* lint-fix

Co-authored-by: JJ Kasper <jj@jjsweb.site>
  • Loading branch information
leerob and ijjk authored Jun 18, 2021
1 parent d0f41f3 commit afa86cc
Showing 1 changed file with 64 additions and 52 deletions.
116 changes: 64 additions & 52 deletions docs/basic-features/script.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,30 @@ description: Next.js helps you optimize loading third-party scripts with the bui

# Script Component

Since version **11**, Next.js has a built-in Script component.
<details>
<summary><b>Version History</b></summary>

Example of usage:
| Version | Changes |
| --------- | ------------------------- |
| `v11.0.0` | `next/script` introduced. |

</details>

The Next.js Script component enables developers to set the loading priority of third-party scripts to save developer time and improve loading performance.

Websites often need third parties for things like analytics, ads, customer support widgets, and consent management. However, these scripts tend to be heavy on loading performance and can drag down the user experience. Developers often struggle to decide where to place them in an application for optimal loading.

With `next/script`, you can define the `strategy` property and Next.js will optimize loading for the script:

- `beforeInteractive`: For critical scripts that need to be fetched and executed **before** the page is interactive, such as bot detection and consent management. These scripts are injected into the initial HTML from the server and run before self-bundled JavaScript is executed.
- `afterInteractive` (**default**): For scripts that can fetch and execute **after** the page is interactive, such as tag managers and analytics. These scripts are injected on the client-side and will run after hydration.
- `lazyOnload` For scripts that can wait to load during idle time, such as chat support and social media widgets.

> **Note:** These loading strategies work the same for inline scripts wrapped with `<Script>`. See the inline scripts example below.
## Usage

Previously, you needed to define `script` tags inside the `Head` of your Next.js page.

```js
// Before
Expand All @@ -23,10 +44,15 @@ function Home() {
</>
)
}
```

With `next/script`, you no longer need to wrap scripts in `next/head`. Further, `next/script` should **not** be used in `pages/_document.js` as `next/script` has client-side functionality to ensure loading order. For example:

```js
// After

// pages/index.js
import Script from 'next/script'

function Home() {
return (
Expand All @@ -37,81 +63,67 @@ function Home() {
}
```

> Note: `next/script` should **not** be wrapped in `next/head`.
> Note: `next/script` should **not** be used in `pages/_document.js` as `next/script` has client-side functionality to ensure loading order.
Three loading strategies will be initially supported for wrapping third-party scripts:
## Examples

- `beforeInteractive`
- script is fetched and executed _before_ page is interactive (i.e. before self-bundled javascript is executed)
- script is injected in SSR’s HTML - similar to self-bundled JS
- `afterInteractive` (**default**)
- script is fetched and executed _after_ page is interactive (i.e. after self-bundled javascript is executed)
- script is injected during hydration and will execute soon after hydration
- `lazyOnload`
- script is injected at `onload`, and will execute in a subsequent idle period (using `requestIdleCallback`)

> Note: above strategies work the same for inline scripts wrapped with `<Script>`.
## Example scenarios
### Loading Polyfills

```js
import Script from 'next/script'

// Loading polyfills before-interactive
<Script
;<Script
src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver"
strategy="beforeInteractive"
/>
```

// Lazy load FB scripts
<Script
### Lazy-Loading

```js
import Script from 'next/script'
;<Script
src="https://connect.facebook.net/en_US/sdk.js"
strategy="lazyOnload"
/>
```

// Use the onLoad callback to execute code on script load
<Script id="stripe-js" src="https://js.stripe.com/v3/" onLoad={() => {
this.setState({stripe: window.Stripe('pk_test_12345')});
}} />
### Executing Code After Loading (`onLoad`)

```js
import Script from 'next/script'
;<Script
id="stripe-js"
src="https://js.stripe.com/v3/"
onLoad={() => {
this.setState({ stripe: window.Stripe('pk_test_12345') })
}}
/>
```

### Inline Scripts

```js
import Script from 'next/script'

// Loading strategy works for inline scripts too
<Script strategy="lazyOnload">
{`document.getElementById('banner').removeClass('hidden')`}
</Script>

// or

<Script
dangerouslySetInnerHTML={{
__html: `document.getElementById('banner').removeClass('hidden')`,
__html: `document.getElementById('banner').removeClass('hidden')`
}}
>
</Script>
/>
```

// All script attributes are forwarded to the final element
<Script
### Forwarding Attributes

```js
import Script from 'next/script'
;<Script
src="https://www.google-analytics.com/analytics.js"
id="analytics"
nonce="XUENAJFW"
data-test="analytics"
/>
```

## Which third-party scripts to wrap with Script Loader

We recommend the following Script Loader strategies for these categories of third-party scripts:

- `beforeInteractive`
- [polyfill.io](https://polyfill.io)
- Bot detection
- Security and Authentication
- User consent management (GDPR)
- `afterInteractive`
- Tag-managers
- Analytics
- `lazyOnload`
- Customer relationship management
- Google feedback
- Chat support widget
- Social networks

0 comments on commit afa86cc

Please sign in to comment.