在 Next.js 中透過動態匯入功能分割程式碼

如何透過程式碼分割和智慧載入策略加快 Next.js 應用程式的速度。

Milica Mihajlija
Milica Mihajlija

您會學到哪些內容?

本文會說明不同類型的程式碼分割,以及如何使用動態匯入功能,加快 Next.js 應用程式的運作速度。

依據路徑和元件的程式碼分割

根據預設,Next.js 會針對每個路徑將您的 JavaScript 拆分為不同的區塊。使用者載入應用程式時,Next.js 只會傳送初始路徑所需的程式碼。使用者在應用程式中瀏覽時,會擷取與其他路徑相關聯的區塊。以路線為基礎的程式碼分割作業可盡量減少一次需要剖析及編譯的指令碼數量,進而縮短網頁載入時間。

雖然以路線為基礎的程式碼分割功能是良好的預設值,但您可以透過元件層級的程式碼分割功能,進一步最佳化載入程序。如果應用程式含有大型元件,建議您將這些元件拆成多個獨立區塊。如此一來,任何非必要或僅在特定使用者互動 (例如點選按鈕) 時才會算繪的大型元件,都可以延遲載入。

Next.js 支援動態 import(),可讓您動態匯入 JavaScript 模組 (包括 React 元件),並將每個匯入項目載入為個別區塊。這可讓您進行元件層級的程式碼分割,並控管資源載入作業,讓使用者只下載所需的程式碼,用於他們正在查看的網站部分。在 Next.js 中,這些元件預設為伺服器端轉譯 (SSR)

動態匯入功能實際運作情形

本文包含多個範例應用程式版本,其中包含一個含有一個按鈕的簡易頁面。點選按鈕後,您會看到可愛的小狗。在瀏覽各個應用程式版本時,您會看到動態匯入與靜態匯入的差異,以及如何使用這兩種匯入方式。

在第一個版本的應用程式中,小狗會顯示在 components/Puppy.js 中。為了在頁面上顯示小狗,應用程式會使用靜態匯入陳述式,匯入 index.js 中的 Puppy 元件:

import Puppy from "../components/Puppy";

如要查看 Next.js 如何將應用程式打包,請在 DevTools 中檢查網路追蹤記錄:

  1. 如要預覽網站,請按下「View App」。然後按下「Fullscreen」圖示 全螢幕

  2. 按下 `Control+Shift+J` 鍵 (在 Mac 上為 `Command+Option+J` 鍵) 開啟開發人員工具。

  3. 按一下 [網路] 分頁標籤。

  4. 勾選「Disable cache」核取方塊。

  5. 請重新載入頁面。

載入網頁時,所有必要程式碼 (包括 Puppy.js 元件) 都會整合在 index.js 中:

「DevTools」網路分頁顯示六個 JavaScript 檔案:index.js、app.js、webpack.js、main.js、0.js 和 dll (動態連結程式庫) 檔案。

按下「Click me」按鈕時,系統只會將小狗 JPEG 的請求加入「Network」分頁:

按下按鈕後,開發人員工具網路分頁顯示相同的六個 JavaScript 檔案和一張圖片。

這種做法的缺點是,即使使用者沒有按下按鈕查看小狗,也必須載入 Puppy 元件,因為 Puppy 已包含在 index.js 中。在這個小範例中,這並不是什麼大問題,但在實際應用程式中,只在必要時載入大型元件通常會帶來巨大的改善。

現在,請查看應用程式的第二個版本,其中靜態匯入已改為動態匯入。Next.js 包含 next/dynamic,可讓您為 Next 中的任何元件使用動態匯入:

import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

請按照第一個範例中的步驟檢查網路追蹤記錄。

首次載入應用程式時,系統只會下載 index.js。這次的大小縮小了 0.5 KB (從 37.9 KB 降至 37.4 KB),因為它不包含 Puppy 元件的程式碼:

開發人員工具網路顯示相同的 6 個 JavaScript 檔案,但 index.js 現在縮減了 0.5 KB。

Puppy 元件現在位於獨立的區塊 1.js 中,只有在您按下按鈕時才會載入:

按下按鈕後的「DevTools Network」分頁,顯示額外的 1.js 檔案和新增至檔案清單底部的圖片。

在實際應用程式中,元件通常遠大,而延遲載入可能會將初始 JavaScript 酬載裁剪上數百 KB。

使用自訂載入指標的動態匯入

在延遲載入資源時,建議您提供載入指標,以防發生任何延遲。在 Next.js 中,您可以為 dynamic() 函式提供額外引數來執行這項操作:

const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});

如要查看載入指標的運作情形,請在 DevTools 中模擬網路連線速度緩慢的情況:

  1. 如要預覽網站,請按下「View App」。然後按下「Fullscreen」圖示 全螢幕

  2. 按下 `Control+Shift+J` 鍵 (在 Mac 上為 `Command+Option+J` 鍵) 開啟開發人員工具。

  3. 按一下 [網路] 分頁標籤。

  4. 勾選「Disable cache」核取方塊。

  5. 在「Throttling」(節流) 下拉式清單中,選取「Fast 3G」(快速 3G)

  6. 按下「按我」按鈕。

現在,當您按一下按鈕時,系統需要花一點時間載入元件,同時應用程式會顯示「載入中…」訊息。

黑色畫面,顯示「

不含 SSR 的動態匯入

如果只需要在用戶端轉譯元件 (例如即時通訊小工具),可以將 ssr 選項設為 false

const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});

結論

Next.js 支援動態匯入功能,可提供元件層級的程式碼分割功能,藉此盡可能減少 JavaScript 酬載,並縮短應用程式載入時間。根據預設,所有元件都是在伺服器端算繪,您可以視需要停用這個選項。