跳到主要內容

腳本最佳化

版面配置腳本

若要為多個路由載入第三方腳本,請匯入 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。這可以透過將主執行緒專用於應用程式程式碼的其餘部分來改善網站的效能。

此策略仍為實驗性功能,僅當 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 的 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"
      />
    </>
  )
}