跳到主要内容

脚本优化

布局脚本

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

app/dashboard/layout.tsx
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
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 策略的脚本通过 Partytown 在 Web Worker 中卸载和执行。 这可以通过将主线程专用于应用程序代码来提高站点的性能。

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

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 的权衡文档 以获取更多信息。

内联脚本

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
'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自定义数据属性。 包含任何额外属性将自动将其转发到最终优化的 <script> 元素中,该元素包含在 HTML 中。

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