How to Embed a Script in NextJS
JavaScript scripts not loading in NextJS? Scripts breaking on AWS Amplify or other host? Want to embed a custom iframe script? Here is how
I've been using NextJS since early this summer... And I'm loving it. 😻
Today I got to use another of its cool perks, and I wanted to share it with you because it might be just the right solution for your client-side JavaScript embedding needs.
I'm talking about Next's Script Component
The Problem
You want to embed an iframe
that requires the integration of some 3rd party custom script
. Or maybe you want to add a tracking scripts, like a Facebook Pixel or Google Analytics. Either way, you are trying to run a JS script on your page.
Traditionally, a web developer would use the HTML <script>
tag inside the header tags.
But what if you are editing a React component somewhere down the NextJS hierarchy tree? What if you want to embed that script (or the element that needs that script) in a page that uses some custom layout component?
Or what if your deployment host breaks your script by not loading it correctly? ─Yes I'm looking at you AWS Amplify!
The NextJS Solution
The Next.js Script
component, next/script
, is an extension of the HTML <script>
element. It enables us to load third-party scripts anywhere in our application without needing to append the script directly to the header (which in NextJS is Head
from next/head
).
On top of that, Script
can save you time and improve loading performance because it allows us to specify when to render the script.
Implementation
To add a third-party script to your application, simply import the next/script
component:
import Script from 'next/script'
You then pick where in you want to place your script call:
export default function YourPage() {
return (
<>
<Script src="https://your-script-link.js" />
</>
)
}
If your script generates something that needs attaching to an HTML element, you can of course simply call Script
to load it, then add the right linkage (for example an ID):
export default function YourPage() {
return (
<>
<Script src="https://domain.com/iframe-embed/third-party-script-to-load.js" />
<div id="your-script-element-id">
</div>
</>
)
}
Extra Perks
Loading Strategy
Besides being extremely easy to place and use, with next/script
, you can decide when to load your third-party script by using the strategy
property:
<Script src="https://www.google-analytics.com/analytics.js" strategy="lazyOnload" />
You can pick one of three strategies:
beforeInteractive
: Load before the page is interactiveafterInteractive
: (default): Load immediately after the page becomes interactivelazyOnload
: Load during idle time
You can find out more about the difference between these on the official documentation
Inline Scripts
next/script
also supports inline scripts: i.e. scripts not loaded from an external file but written within the <Script>
tag.
You can either place a script inside of curly braces and wrap it inside an open and close <Sctipt>
tag:
<Script id="show-banner" strategy="lazyOnload">
{`document.getElementById('banner').classList.remove('hidden')`}
</Script>
Or you can use the dangerouslySetInnerHTML
property in a self-closing tag:
<Script
id="show-banner"
dangerouslySetInnerHTML={{
__html: `document.getElementById('banner').classList.remove('hidden')`,
}}
/>
Note that:
- You can't use the
beforeInteractive
strategy with inline scripts. - You must provide an
id
to allow Next.js to track and optimise the script
Executing Code After Loading
Another cool thing you can do with next/script
is to run some JavaScript code only after the script has loaded.
For example, let's say you need to run an API script and then trigger a function that displays a pop-up. You can do it that too:
import { useState } from 'react'
import Script from 'next/script'
export default function Checkout() {
const [stripe, setStripe] = useState(null)
return (
<>
<Script
id="stripe-js"
src="https://js.stripe.com/v3/"
onLoad={() => {
setStripe({ stripe: window.Stripe('pk_test_12345') })
}}
/>
</>
)
}
Note that you can only execute code if you are using either the afterInteractive
(default) or the beforeInteractive
strategies.
Additional Attributes
You can also add other attributes to the Script
element that are not used directly by the component, but that you might need to pass to the final, optimised <script>
element that is eventually outputted to the page. For example a nonce
or a custom data-
attribute.