跳到内容

脚本优化

布局脚本

要为多个路由加载第三方脚本,请导入 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 代码之前以及任何页面 hydration 发生之前加载脚本。
  • afterInteractive:(默认)尽早加载脚本,但在页面上发生一些 hydration 之后加载。
  • lazyOnload:稍后在浏览器空闲时间加载脚本。
  • worker:(实验性)在 Web worker 中加载脚本。

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

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

警告: worker 策略尚不稳定,尚不适用于 App Router。 请谨慎使用。

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

此策略仍处于实验阶段,只有在 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 的 tradeoffs 文档以获取更多信息。

内联脚本

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