next.js: next/script using beforeInteractive strategy don't work with alert

What version of Next.js are you using?

11.0.0

What version of Node.js are you using?

14.17.0

What browser are you using?

Chrome

What operating system are you using?

macOS

How are you deploying your application?

next start

Describe the Bug

When I try to add next/script into “_document” or “_app” files calling a inline alert function, don’t work using beforeInteractive strategy, but when I don’t explicitly inform a strategy value, it works.

image

Expected Behavior

Should work with beforeInteractive strategy inside _document.js or _app.js.

To Reproduce

Just add <Script strategy="beforeInteractive">{`alert('Not work')`}</Script> to _document.js or _app.js, and try to run with next build && next start.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 29 (17 by maintainers)

Commits related to this issue

Most upvoted comments

seems the narrative has changed regarding this in the doc: https://nextjs.org/docs/basic-features/script#beforeinteractive

It is stated that:

This strategy only works inside _document.js

However, if you try with their example, it does not work at all:

// In _document.js
import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
        <Script
          src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"
          strategy="beforeInteractive"
        ></Script>
      </body>
    </Html>
  )
}

Put it in the app does work.

I am curious why

Another use-case is a code that detects user selected light / dark theme, to avoid flickering on the first load.

@janicklas-ralph thanks for the heads-up.

My initial idea was to insert a simple code that checks for the presence of the authentication token. But then I had a moment of realization. Isn’t inline script together with beforeInteractive strategy same as this code?

<Head>
  <script dangerouslySetInnerHTML={{
    __html: ` // code here`
  }}
  />
<Head />

Another use-case is a code that detects user selected light / dark theme, to avoid flickering on the first load.

Funny enough you should mention it, this is exactly the use case and strategy that Josh Comeau writes about in his article on how to achieve the perfect dark theme, and how Brian Lovin implemented this technique in his personal site which is written using nextjs

Side note: if anyone is happening to stumble on this looking to load scripts before interactive using this component, it seems to not work on version 12 of next either.

Hi. Apologize for the delayed response. An update on this - It was intentional to not allow inline scripts with beforeInteractive since we noticed it hurt performance. I’m working on adding another strategy to load inline scripts with beforeInteractive.

12.2 is out since yesterday!

Sorry for the confusion here, let me try to explain.

Yes, the narrative has changed, when using Script together with the beforeInteractive strategy, it should now be placed in _document. (Reflected in the docs now, and explained why. Please see https://nextjs.org/docs/basic-features/script#beforeinteractive.)

The way it currently works is only if you put Script in Head. There is a known issue when Script is in Body as pointed out https://github.com/vercel/next.js/issues/26343#issuecomment-1157267569

We are aware of that, please see: https://github.com/vercel/next.js/issues/37741#issuecomment-1157358712, and going to fix this soon!

Hope that helps! 💚

@janicklas-ralph thanks for the heads-up.

My initial idea was to insert a simple code that checks for the presence of the authentication token. But then I had a moment of realization. Isn’t inline script together with beforeInteractive strategy same as this code?

<Head>
  <script dangerouslySetInnerHTML={{
    __html: ` // code here`
  }}
  />
<Head />

The docs says it shouldn’t be used inside _document

https://nextjs.org/docs/basic-features/script

haven’t tried _app

Sorry for saying this, but I think it is bad that next js official doc continues to leave the non-working/erroneous example out there. Knowingly.

Should this not be added to the docs that dangerouslySetInnerHTML does not work with beforeInteractive strategy?