Skip to main content

脚本优化

Layout 脚本

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

import Script from "next/script";

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

export default function DashboardLayout({ children }) {
return (
<>
<section>{children}</section>
<Script src="https://example.com/script.js" />
</>
);
}

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

应用程序脚本

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

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>
);
}
import Script from "next/script";

export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
<Script src="https://example.com/script.js" />
</html>
);
}

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

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

strategy

尽管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标志时才能使用:

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

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

npm run dev

您将看到如下说明:Please install Partytown by running npm install @builder.io/partytown

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

import Script from "next/script";

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

export default function Home() {
return (
<>
<Script src="https://example.com/script.js" strategy="worker" />
</>
);
}

在 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"被定义为代码的第一行:

"use client";

import Script from "next/script";

export default function Page() {
return (
<>
<Script
src="https://example.com/script.js"
onLoad={() => {
console.log("Script has loaded");
}}
/>
</>
);
}
"use client";

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 参考文档,以了解每个事件处理程序并查看示例。

附加属性

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

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"
/>
</>
);
}
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"
/>
</>
);
}