跳到内容

如何加载和优化脚本

应用程序脚本

要为所有路由加载第三方脚本,请导入 next/script 并将脚本直接包含在您的自定义 _app

pages/_app.js
import Script from 'next/script'
 
export default function MyApp({ Component, pageProps }) {
  return (
    <>
      <Component {...pageProps} />
      <Script src="https://example.com/script.js" />
    </>
  )
}

当应用程序中的*任何*路由被访问时,此脚本都将加载并执行。Next.js 将确保脚本**只加载一次**,即使用户在多个页面之间导航。

**建议**:我们建议仅在特定页面或布局中包含第三方脚本,以最大程度地减少对性能不必要的任何影响。

策略

尽管 next/script 的默认行为允许您在任何页面或布局中加载第三方脚本,但您可以通过使用 strategy 属性来微调其加载行为

  • beforeInteractive:在任何 Next.js 代码和任何页面水合发生之前加载脚本。
  • afterInteractive:(**默认**)在页面上发生一些水合后,尽早加载脚本。
  • lazyOnload:在浏览器空闲时稍后加载脚本。
  • worker:(实验性)在 Web Worker 中加载脚本。

请参阅 next/script API 参考文档,以了解每个策略及其用例的更多信息。

将脚本卸载到 Web Worker(实验性)

警告: worker 策略尚不稳定,并且尚不支持 App Router。请谨慎使用。

使用 worker 策略的脚本将通过 Partytown 卸载并在 Web Worker 中执行。这可以通过将主线程专门用于应用程序的其余代码来提高站点的性能。

此策略仍处于实验阶段,仅当 nextScriptWorkers 标志在 next.config.js 中启用时才能使用。

next.config.js
module.exports = {
  experimental: {
    nextScriptWorkers: true,
  },
}

然后,运行 next(通常是 npm run devyarn dev),Next.js 将指导您安装所需的包以完成设置。

终端
npm run dev

您会看到类似以下说明:请通过运行 npm install @builder.io/partytown 安装 Partytown。

设置完成后,定义 strategy="worker" 将自动在您的应用程序中实例化 Partytown 并将脚本卸载到 Web Worker。

pages/home.tsx
import Script from 'next/script'
 
export default function Home() {
  return (
    <>
      <Script src="https://example.com/script.js" strategy="worker" />
    </>
  )
}

在 Web Worker 中加载第三方脚本时需要考虑许多权衡。请参阅 Partytown 的 权衡 文档以获取更多信息。

使用自定义 Partytown 配置

虽然 worker 策略不需要任何额外的配置即可工作,但 Partytown 支持使用配置对象来修改其某些设置,包括启用 debug 模式以及转发事件和触发器。

如果您想添加其他配置选项,可以将其包含在自定义 _document.js 中使用的 <Head /> 组件中。

_pages/document.jsx
import { Html, Head, Main, NextScript } from 'next/document'
 
export default function Document() {
  return (
    <Html>
      <Head>
        <script
          data-partytown-config
          dangerouslySetInnerHTML={{
            __html: `
              partytown = {
                lib: "/_next/static/~partytown/",
                debug: true
              };
            `,
          }}
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

为了修改 Partytown 的配置,必须满足以下条件:

  1. 必须使用 data-partytown-config 属性才能覆盖 Next.js 使用的默认配置。
  2. 除非您决定将 Partytown 的库文件保存在单独的目录中,否则必须在配置对象中包含 lib: "/_next/static/~partytown/" 属性和值,以便让 Partytown 知道 Next.js 存储必要静态文件的位置。

**注意**:如果您正在使用 资产前缀 并希望修改 Partytown 的默认配置,则必须将其包含在 lib 路径中。

请查看 Partytown 的 配置选项 以查看可以添加的其他属性的完整列表。

内联脚本

脚本组件也支持内联脚本,即不从外部文件加载的脚本。它们可以通过将 JavaScript 放在大括号内来编写。

<Script id="show-banner">
  {`document.getElementById('banner').classList.remove('hidden')`}
</Script>

或者使用 dangerouslySetInnerHTML 属性

<Script
  id="show-banner"
  dangerouslySetInnerHTML={{
    __html: `document.getElementById('banner').classList.remove('hidden')`,
  }}
/>

**警告**:必须为内联脚本分配一个 id 属性,以便 Next.js 跟踪和优化脚本。

执行附加代码

事件处理程序可以与脚本组件一起使用,以在特定事件发生后执行附加代码。

  • onLoad:脚本加载完成后执行代码。
  • onReady:脚本加载完成后以及每次组件挂载时执行代码。
  • onError:如果脚本加载失败,则执行代码。

这些处理程序仅在 next/script 被导入并在 客户端组件 中使用时才有效,其中 "use client" 被定义为代码的第一行。

pages/index.tsx
import Script from 'next/script'
 
export default function Page() {
  return (
    <>
      <Script
        src="https://example.com/script.js"
        onLoad={() => {
          console.log('Script has loaded')
        }}
      />
    </>
  )
}

请参阅 next/script API 参考,以了解每个事件处理程序的更多信息并查看示例。

附加属性

有许多可以分配给 <script> 元素的 DOM 属性不被脚本组件使用,例如 nonce自定义数据属性。包含任何附加属性将自动将其转发到 HTML 中最终的优化 <script> 元素。

pages/index.tsx
import Script from 'next/script'
 
export default function Page() {
  return (
    <>
      <Script
        src="https://example.com/script.js"
        id="example-script"
        nonce="XUENAJFW"
        data-test="script"
      />
    </>
  )
}