I try to understand how the next.js Script tag with the strategy beforeInteractive works. For testing i just used lodash. But i keep getting a ReferenceError: _ is not defined. I thought when a script is loaded with beforeInteractive it should be globally available inside my page Component since it get injected into the initial Html from the server and i could use it for example in the useEffect hook to alter a div. Can someone explain to me why it's not working or what i'm doing wrong? I don't installed it via npm because im trying to figure out how it works.
I have a simple _document.js and i added a Next.js script tag with the strategy beforeInteractive to this _document.js. The next.js docs says: This strategy only works inside _document.js and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
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://unpkg.com/[email protected]"
strategy="beforeInteractive"
></Script>
</body>
</Html>
)
}
Then i have a simple page Component inside the pages folder. I added the getServerSideProps function to use ServerSideRendering.
If you export a function called getServerSideProps (Server-Side Rendering) from a page, Next.js will pre-render this page on each request using the data returned by getServerSideProps.
import Head from 'next/head';
import {useEffect, useState} from 'react';
const TestComponent = () => {
const [change,setChange] = useState('not changed');
useEffect(()=> {
console.log(_);
setChange(_.join(['one','two'],' - '));
});
return (
<>
<Head>
<title>Test</title>
</Head>
<div>{change}</div>
</>
);
};
export async function getServerSideProps(context) {
return {
props: {},
}
}
export default TestComponent;
CodePudding user response:
First and foremost, I'm failing to see virtually any reason you'd want to do this, when you can (and should) simply use install it to node_modules
. You're also going to possibly run the risk of the bundle having issues if the library type isn't a module and the next configuration requires a module.
Solution based on the question:
There's two ways. Firstly, see the docs on this exact thing.
Please use the above method mentioned in the docs.
If that's not an option for whatever reason...
The second is a less than ideal, but working solution.
Create a folder for your static files. Ex: <root>/static/js/hello.js
. Then in your _document
file,
<script type="text/javascript" src="/static/hello.js"></script>
CodePudding user response:
Putting aside the fact that you should be importing Lodash as a node module, there does seem to be an issue when using next/script
in _document
(no matter what the external script actually is).
As an alternative, you can use the <script>
tag directly in the _document
's <Head>
with the defer
property. This closely matches what the next/script
would output.
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<script
type="text/javascript"
src="https://unpkg.com/[email protected]/lodash.js"
defer
></script>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}