How to Embed a Script in NextJS

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 interactive
  • afterInteractive: (default): Load immediately after the page becomes interactive
  • lazyOnload: 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.

Â