跳到主要內容

指令碼最佳化

應用程式指令碼

若要為所有路由載入第三方指令碼,請匯入 next/script 並將指令碼直接包含在您的自訂 _app

pages/_app.js
import Script from 'next/script'
 
export default function MyApp({ Component, pageProps }) {
  return (
    <>
      <Component {...pageProps} />
      <Script src="https://example.com/script.js" />
    </>
  )
}

此指令碼將在存取您應用程式中的*任何*路由時載入和執行。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 文件以取得更多資訊。

使用自訂 Partytown 設定

雖然 `worker` 策略不需要任何額外設定即可運作,但 Partytown 支援使用設定物件來修改其某些設定,包括啟用 `debug` 模式以及轉發事件和觸發器。

如果您想新增其他設定選項,您可以將其包含在 自訂 `_document.js` 中使用的 `<Head />` 元件內

_pages/document.jsx
import { Html, Head, Main, NextScript } from 'next/document'
 
export default function Document() {
  return (
    <Html>
      <Head>
        <script
          data-partytown-config
          dangerouslySetInnerHTML={{
            __html: `
              partytown = {
                lib: "/_next/static/~partytown/",
                debug: true
              };
            `,
          }}
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

為了修改 Partytown 的設定,必須滿足以下條件

  1. 必須使用 `data-partytown-config` 屬性才能覆寫 Next.js 使用的預設設定
  2. 除非您決定將 Partytown 的函式庫檔案儲存在單獨的目錄中,否則必須在設定物件中包含 `lib: "/_next/static/~partytown/"` 屬性和值,以讓 Partytown 知道 Next.js 儲存必要靜態檔案的位置。

**注意**:如果您正在使用 asset prefix 並且想要修改 Partytown 的預設設定,則必須將其作為 `lib` 路徑的一部分包含在內。

請查看 Partytown 的 configuration options 以查看可以新增的其他屬性的完整列表。

內聯指令碼

內聯指令碼,或非從外部檔案載入的指令碼,也受到 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` 並在 Client Component 內部使用時才有效,其中 `"use client"` 被定義為程式碼的第一行

pages/index.tsx
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 中。

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