[英]Why does the next.js Script tag with the beforeInteractive strategy don't load thirdParty script?
I try to understand how the next.js Script tag with the strategy beforeInteractive works.我尝试了解 next.js Script 标记与 beforeInteractive 策略的工作原理。 For testing i just used lodash.
为了测试,我只使用了 lodash。 But i keep getting a ReferenceError: _ is not defined .
但我不断收到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.
我认为当使用 beforeInteractive 加载脚本时,它应该在我的页面组件中全局可用,因为它是从服务器注入到初始 Html 中的,我可以在 useEffect 挂钩中使用它来更改 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.
我没有通过 npm 安装它,因为我试图弄清楚它是如何工作的。
I have a simple _document.js and i added a Next.js script tag with the strategy beforeInteractive to this _document.js.我有一个简单的 _document.js,并在这个 _document.js 中添加了一个带有 beforeInteractive 策略的 Next.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 (ie the script will load when any page in the application has been loaded server-side).
next.js 文档说:此策略仅在 _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://unpkg.com/lodash@4.17.20"
strategy="beforeInteractive"
></Script>
</body>
</Html>
)
}
Then i have a simple page Component inside the pages folder.然后我在 pages 文件夹中有一个简单的页面组件。 I added the getServerSideProps function to use ServerSideRendering.
我添加了 getServerSideProps 函数来使用 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.如果您从页面导出名为 getServerSideProps(服务器端渲染)的函数,Next.js 将使用 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;
Update更新
Seems like it is indeed a bug which is fixed but not released yet https://github.com/vercel/next.js/discussions/37098似乎它确实是一个已修复但尚未发布的错误https://github.com/vercel/next.js/discussions/37098
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).撇开您应该将 Lodash 作为节点模块导入这一事实不谈,在
_document
中使用next/script
似乎确实存在问题(无论外部脚本实际上是什么)。
It turns out this is a Next.js bug that has been addressed in this PR in pre-release versionv12.1.7-canary.8 .事实证明,这是一个 Next.js 错误,已在此PR中的预发布版本v12.1.7-canary.8 中解决。 To fix the issue in your project simply update Next.js to version >=12.2.0 (
npm install next@latest
).要解决项目中的问题,只需将 Next.js 更新到 >=12.2.0 版本(
npm install next@latest
)。
As an alternative, you can use the <script>
tag directly in the _document
's <Head>
with the defer
property.作为替代方案,您可以直接在
_document
的<Head>
中使用带有defer
属性的<script>
标记。 This closely matches what the next/script
would output.这与
next/script
将输出的内容非常匹配。
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<script
type="text/javascript"
src="https://unpkg.com/lodash@4.17.20/lodash.js"
defer
></script>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
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
.首先,当您可以(并且应该)简单地使用 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.如果库类型不是模块并且下一个配置需要模块,您还可能会冒包出现问题的风险。
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
.例如:
<root>/static/js/hello.js
。 Then in your _document
file,然后在你的
_document
文件中,
<script type="text/javascript" src="/static/hello.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.