Menu

脚本优化

布局脚本

要为多个路由加载第三方脚本,请导入 next/script 并直接在布局组件中包含该脚本:

app/dashboard/layout.tsx
TypeScript
import Script from "next/script";
 
export default function DashboardLayout ({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <>
      <section>{children}</section>
      <Script src="https://example.com/script.js" />
    </>
  );
}

当用户访问文件夹路由 (如 dashboard/page.js) 或任何嵌套路由 (如 dashboard/settings/page.js) 时,会获取第三方脚本。即使用户在同一布局中的多个路由之间导航,Next.js 也会确保脚本只加载一次

应用程序脚本

要为所有路由加载第三方脚本,请导入 next/script 并直接在根布局中包含该脚本:

app/layout.tsx
TypeScript
import Script from "next/script";
 
export default function RootLayout ({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
      <Script src="https://example.com/script.js" />
    </html>
  );
}

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

建议:我们建议只在特定页面或布局中包含第三方脚本,以尽量减少对性能的不必要影响。

策略

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

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

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

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

警告: worker 策略尚不稳定,目前还不能与 app 目录一起使用。请谨慎使用。

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

该策略仍处于实验阶段,只有在 next.config.js 中启用 nextScriptWorkers 标志时才能使用:

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

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

Terminal
npm run dev

你会看到类似这样的指示:请通过运行 npm install @builder.io/partytown 来安装 Partytown

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

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

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

在 web worker 中加载第三方脚本时需要权衡考虑许多因素。请查看 Partytown 的权衡文档以了解更多信息。

内联脚本

Script 组件也支持内联脚本,即不从外部文件加载的脚本。它们可以通过将 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 能够跟踪和优化脚本。

执行额外代码

可以使用 Script 组件的事件处理程序在某个事件发生后执行额外的代码:

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

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

app/page.tsx
TypeScript
"use client";
 
import Script from "next/script";
 
export default function Page () {
  return (
    <>
      <Script
        src="https://example.com/script.js"
        onLoad={() => {
          console.log ("脚本已加载");
        }}
      />
    </>
  );
}

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

额外属性

有许多 DOM 属性可以分配给 <script> 元素,但 Script 组件并未使用,如 nonce自定义数据属性。包含任何额外的属性将自动转发到最终优化的 <script> 元素中,该元素包含在 HTML 中。

app/page.tsx
TypeScript
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"
      />
    </>
  );
}