在本程式碼研究室中,我們將預先載入及預先擷取一些資源,藉此提升下列網頁的效能:
測量
請先評估網站成效,再進行任何最佳化調整。
- 如要預覽網站,請按下「查看應用程式」,然後按下「全螢幕」圖示
。
在 Glitch 的即時版本上執行 Lighthouse 成效稽核 (依序點選「Lighthouse」>「Options」>「Performance」)。(另請參閱「透過 Lighthouse 找出成效提升機會」)。
如果資源擷取時間較晚,Lighthouse 會顯示下列稽核失敗結果:

- 按下 `Control+Shift+J` 鍵 (在 Mac 上為 `Command+Option+J` 鍵) 開啟開發人員工具。
- 按一下 [網路] 分頁標籤。

HTML 文件中的 Link 元素 (<link>
) 不會擷取 main.css
檔案,但個別的 JavaScript 檔案 fetch-css.js
會在 window.onLoad
事件後,將 Link 元素附加至 DOM。也就是說,瀏覽器完成剖析及執行 JS 檔案後,才會擷取檔案。同樣地,只有在 CSS 檔案下載完成後,才會擷取 main.css
內指定的網頁字型 (K2D.woff2
)。
關鍵要求鏈結代表瀏覽器優先擷取的資源順序。這個網頁目前看起來如下:
├─┬ / (initial HTML file)
└── fetch-css.js
└── main.css
└── K2D.woff2
由於 CSS 檔案位於要求鏈的第三層,Lighthouse 已將其識別為延遲探索到的資源。
預先載入重要資源
main.css
檔案是網頁載入後立即需要的關鍵資產。對於這類在應用程式中稍晚才擷取的重要檔案,請使用連結預先載入標記,在文件的標題中新增 Link 元素,通知瀏覽器提早下載。
為這個應用程式新增預先載入標記:
<head>
<!-- ... -->
<link rel="preload" href="main.css" as="style">
</head>
as
屬性用於識別要擷取的資源類型,as="style"
則用於預先載入樣式表檔案。
重新載入應用程式,並查看開發人員工具中的「網路」面板。

請注意,瀏覽器會在負責擷取 CSS 檔案的 JavaScript 甚至還沒完成剖析時,就擷取該檔案。透過預先載入,瀏覽器會知道要預先擷取資源,並假設該資源對網頁至關重要。
如果使用不當,預先載入可能會對效能造成負面影響,因為系統會對未使用的資源發出不必要的要求。在這個應用程式中,details.css
是位於專案根目錄的另一個 CSS 檔案,但用於獨立的 /details route
。如要顯示預先載入的錯誤用法範例,請一併為這項資源新增預先載入提示。
<head>
<!-- ... -->
<link rel="preload" href="main.css" as="style">
<link rel="preload" href="details.css" as="style">
</head>
重新載入應用程式,然後查看「Network」面板。
即使網頁未使用 details.css
,系統仍會要求擷取。

如果預先載入的資源在網頁載入後幾秒內未使用,Chrome 會在「控制台」面板中顯示警告。

您可以根據這項警告,判斷是否有任何預先載入的資源未立即供網頁使用。現在可以移除這個網頁不必要的預先載入連結。
<head>
<!-- ... -->
<link rel="preload" href="main.css" as="style">
<link rel="preload" href="details.css" as="style">
</head>
如要查看可擷取的所有資源類型清單,以及 as
屬性應使用的正確值,請參閱 MDN 預先載入文章。
預先擷取未來資源
預先擷取是另一項瀏覽器提示,可用於要求取得其他導覽路徑使用的資產,但優先順序低於目前網頁所需的重要資產。
在這個網站中,點選圖片會前往另一個details/
路徑。
另一個 CSS 檔案 details.css
包含這個簡單網頁所需的所有樣式。在 index.html
中新增連結元素,預先擷取這項資源。
<head>
<!-- ... -->
<link rel="prefetch" href="details.css">
</head>
如要瞭解這項操作如何觸發檔案要求,請在開發人員工具中開啟「網路」面板,然後取消勾選「停用快取」選項。

重新載入應用程式,並注意在擷取所有其他檔案後,系統如何對 details.css
發出優先順序極低的要求。

開啟開發人員工具後,按一下網站上的圖片,即可前往 details
頁面。
由於 details.html
中使用連結元素擷取 details.css
,因此系統會如預期對資源提出要求。

在開發人員工具中按一下 details.css
網路要求,即可查看詳細資料。你會發現檔案是從瀏覽器的磁碟快取中擷取。

預先擷取功能會利用瀏覽器的閒置時間,提早要求其他網頁所需的資源。這樣一來,瀏覽器就能更快快取資產,並在需要時從快取提供資產,加快日後的導覽要求。
使用 webpack 預先載入和預先擷取
「使用程式碼分割減少 JavaScript 酬載」一文探討如何使用動態匯入,將套件分割成多個區塊。我們將以簡單的應用程式為例,說明如何動態匯入 Lodash 中的模組 (表單提交時)。

您可以在這裡存取這個應用程式的 Glitch。
下列程式碼區塊位於 src/index.js,
中,負責在點選按鈕時動態匯入方法。
form.addEventListener("submit", e => {
e.preventDefault()
import('lodash.sortby')
.then(module => module.default)
.then(sortInput())
.catch(err => { alert(err) });
});
分割套件可減少初始大小,進而縮短網頁載入時間。webpack 4.6.0 版支援預先載入或預先擷取動態匯入的區塊。以這個應用程式為例,lodash
方法可在瀏覽器閒置時預先擷取;使用者按下按鈕時,系統不會延遲擷取資源。
在動態匯入中使用特定的 webpackPrefetch
註解參數,預先擷取特定區塊。
以下是這個特定應用程式的顯示畫面。
form.addEventListener("submit", e => {
e.preventDefault()
import(/* webpackPrefetch: true */ 'lodash.sortby')
.then(module => module.default)
.then(sortInput())
.catch(err => { alert(err) });
});
應用程式重新載入後,webpack 會將資源的預先擷取代碼插入文件標題。您可以在開發人員工具的「元素」面板中查看這項資訊。
在「網路」面板中觀察要求,也會發現這個區塊是在所有其他資源要求後,以低優先順序擷取。

雖然預先擷取更適合這個用途,但 webpack 也支援預先載入動態匯入的區塊。
import(/* webpackPreload: true */ 'module')
結論
完成本程式碼研究室後,您應該就能充分瞭解預先載入或預先擷取特定資產,如何改善網站的使用者體驗。請務必注意,這些技術不適用於所有資源,使用不當可能會損害效能。只預先載入或預先擷取特定資源,才能獲得最佳成效。
摘要:
- 對於稍晚才發現但對目前網頁至關重要的資源,請使用預先載入。
- 針對未來導覽路徑或使用者動作所需的資源,使用預先擷取。
目前並非所有瀏覽器都支援預先載入和預先擷取。也就是說,並非所有應用程式使用者都能感受到效能提升。
如要進一步瞭解預先載入和預先擷取對網頁特定層面的影響,請參閱下列文章: