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&lt;Header&gt; 标记内粘贴了css 文件链接,它们似乎工作得很好。当我尝试使用 &lt;script&gt; 标记对 javascript 文件执行相同操作时,它不会执行这些脚本中的代码。但我可以在 chrome 开发工具中看到它们加载了 http 200

我尝试使用来自npm 的名为Loadjs 的库来加载componentDidMount 中的脚本,但我得到的结果与使用&lt;script&gt; 标记完全相同。

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.jsmain-script.js。我把这些像这样 &lt;root&gt;/static/entry-script.js&lt;root&gt;/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 页面的 &lt;head&gt; 中,而无需进行字符转义、格式化和一般假装我们是t 实际上只是最终构建了一个 HTML 页面。

在许多用例中,您可能希望脚本在不连接网络的情况下运行。例如:第 3 方脚本、监控 / 分析脚本,预计在 &lt;head&gt; 中,没有单独的网络负载。其中许多都被缩小、损坏、随叫随到,只是应该被复制、粘贴、继续生活。

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】:

这对我有用:

为您的静态文件创建一个文件夹:

&lt;root&gt;/static/hello.js

在你的 index.js 中

&lt;root&gt;/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> 标签,但不执行它们的主要内容,如果未能解决你的问题,请参考以下文章

React / JSX:渲染的 <script> 标记将等号和引号添加到异步属性

Next.js 使用 <img> 标签构建失败

Next js 在加载页面内容时在顶部显示 0 一秒钟

致力于带给开发者最佳体验,Next.js 11 版本发布!

Next.js 11正式发布,React 应用的后端渲染

在加载 <script> 标记之前等待 turbolinks 加载