Next.js 加载 <script> 标签,但不执行它们
Posted
技术标签:
【中文标题】Next.js 加载 <script> 标签,但不执行它们【英文标题】:Next.js Loads <script> tags but it doesn't execute them 【发布时间】:2019-06-01 16:46:32 【问题描述】:我正在将现有的 React 应用程序集成到 Next.js 中,主要用于 SEO 功能。
我在Next.js
的<Header>
标记内粘贴了css 文件链接,它们似乎工作得很好。当我尝试使用 <script>
标记对 javascript 文件执行相同操作时,它不会执行这些脚本中的代码。但我可以在 chrome 开发工具中看到它们加载了 http 200
。
我尝试使用来自npm
的名为Loadjs
的库来加载componentDidMount
中的脚本,但我得到的结果与使用<script>
标记完全相同。
在Next.js
中是否有合适的方法来做我不知道的简单事情?
这是pages/index.js
文件中包含的代码。
import React from "react"
import Head from 'next/head'
import MyAwesomeComponent from "../components/mycomponent.js"
export default () => (
<div>
<Head>
<link type="text/css" rel="stylesheet" href="static/css/chatwidget.css" />
<link type="text/css" rel="stylesheet" href="static/css/download.css" />
<script type="text/javascript" src="static/libs/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/malihu-custom-scrollbar-plugin@3.1.5/jquery.mCustomScrollbar.concat.min.js"></script>
<script type="text/javascript" src="static/libs/bootstrap.min.js"></script>
<script type="text/javascript" src="static/libs/owl.carousel.min.js"></script>
<script type="text/javascript" src="static/scripts/chatHead.js"></script>
<script type="text/javascript" src="static/libs/jquery.magnific-popup.js"></script>
</Head>
<MyAwesomeComponent /> /* a simple React component that returns : <p>Hello World </p>*/
</div>
)
抱歉回复晚了。
事实证明,我链接的所有scripts
都错过了一个脚本,该脚本实际上会为每个操作运行functions
。
【问题讨论】:
您是否尝试在自定义文档中输入脚本标签。查看此页面了解如何在 nextjs 中创建自定义文档标签的更多信息。nextjs.org/docs/#custom-document 您找到解决方案了吗?可以分享一下吗? 嘿@Sleek,看看我的回答是否适合你 @Sleek 脚本正在运行,但我没有从中调用任何函数,因此它们似乎不起作用。 【参考方案1】:我写了一篇文章详细阐述了这个问题,希望它能够派上用场:
https://www.devtwins.com/blog/how-to-add-a-third-party-script-to-a-nextjs-website
【讨论】:
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review【参考方案2】:使用 Next.js v11,您可以使用 Next 组件Script
https://nextjs.org/blog/next-11#script-optimization
<Script
src="..."
strategy="beforeInteractive"
/>
【讨论】:
我用过。它没有加载谷歌分析代码。知道如何实现这一目标吗?【参考方案3】:这是我尝试过的,它对我有用。
我使用了两个文件entry-script.js
和main-script.js
。我把这些像这样
<root>/static/entry-script.js
和 <root>/static/main-script.js
entry-script.js
的内容如下。
(function (d, t)
t = d.createElement("script");
t.setAttribute("src", "/static/main-script.js");
d.getElementsByTagName("head")[0].appendChild(t);
)(document);
主要逻辑在文件main-script.js
中。
在 NextJS 的文件 _doucment.js
中,我在正文中包含了我的文件 entry-script.js
,如下所示
class MyDocument extends Document
render()
return (
<html>
<Head>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
</Head>
<body>
<script
type="text/javascript"
src="/static/entry-script.js"
></script>
<Main />
<NextScript />
</body>
</Html>
);
export default MyDocument;
MyDocument.getInitialProps = async (ctx) =>
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage(
enhanceApp: (App) => (props) => sheets.collect(<App ...props />),
);
const initialProps = await Document.getInitialProps(ctx);
return
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [
...React.Children.toArray(initialProps.styles),
sheets.getStyleElement(),
],
;
;
【讨论】:
【参考方案4】:通过以下方法,您可以轻松地将脚本文件的 原始脚本文本 放入生成的 Next.js HTML 页面的 <head>
中,而无需进行字符转义、格式化和一般假装我们是t 实际上只是最终构建了一个 HTML 页面。
在许多用例中,您可能希望脚本在不连接网络的情况下运行。例如:第 3 方脚本、监控 / 分析脚本,预计在 <head>
中,没有单独的网络负载。其中许多都被缩小、损坏、随叫随到,只是应该被复制、粘贴、继续生活。
Next.js 让这变得非常困难,假装 Web 开发的一切现在都是神奇的 React 和 Webpack(我希望是吧?)
我发现的最佳开发者体验方式是这样做:
_document.js
...
<Head>
<script type="text/javascript" dangerouslySetInnerHTML= __html: process.env.rawJsFromFile ></script>
</Head>
...
next.config.js
https://github.com/vercel/next.js/blob/canary/packages/next/next-server/server/config.ts#L33
module.exports =
env:
rawJsFromFile: fs.readFileSync('./rawJsFromFile.js').toString()
rawJsFromFile.js
alert('Freedom!!!!!!!!!!!!!!!');
// and other 3rd party script junk, heck even minified JS is fine too if you need
希望这可以使我免于遭受数小时的挫败感...?
【讨论】:
谢谢约翰..这非常适合它。我已经尝试过危险的SetInnerHTML,但是 webpack 正在修改包含的 js。这是包含跟踪 js 的完美方式,没有来自 ts 的任何投诉,无需将其作为单独的脚本加载,也没有 js 被修改的风险。万分感谢! 如果您包含带有内联代码的 3rd 方脚本,这是正确的答案。 \o/【参考方案5】:希望这可以帮助你Nextjs public folder
将静态文件夹移动到根目录下的公用文件夹中
export default () => (
<div>
<Head>
<link type="text/css" rel="stylesheet" href="/static/css/chatwidget.css" />
<link type="text/css" rel="stylesheet" href="/static/css/download.css" />
<script type="text/javascript" src="/static/libs/jquery.min.js"></script>
...
</Head>
<MyAwesomeComponent />
</div>
)
【讨论】:
【参考方案6】:你也可以这样运行js代码
<script
dangerouslySetInnerHTML=
__html: `
let a = 1;
functionCall();
`,
></script>
【讨论】:
【参考方案7】:这对我有用:
为您的静态文件创建一个文件夹:
<root>/static/hello.js
在你的 index.js 中
<root>/pages/index.js
import Head from 'next/head';
import MyAwesomeComponent from '../components/mycomponent';
export default () => (
<div>
<Head>
<script type="text/javascript" src="/static/hello.js"></script>
</Head>
<MyAwesomeComponent />
</div>
)
希望对您有所帮助,
问候
【讨论】:
这在开发环境中有效吗?因为我试过这个,似乎它不起作用。 这里也一样。试图找到一个热重载的解决方案。 @Shadab 有任何进展吗? 是的,几年前在本地测试过 :),你们用的是哪个 nextjs 版本? 嗨@AndreVitorio 我已经添加了一个答案,看看它。它在开发环境中为我工作。 你的想法是对的,但我认为你的意思是将脚本放在/public
而不是 /static
以上是关于Next.js 加载 <script> 标签,但不执行它们的主要内容,如果未能解决你的问题,请参考以下文章