在本程式碼研究室中,我們透過預先載入和預先擷取一些資源,改善下列網頁的效能:
測量
請先評估網站成效,再進行任何最佳化調整。
- 如要預覽網站,請按下「View App」。然後按下「Fullscreen」圖示 。
在 Glitch 的實際版本上執行 Lighthouse 效能稽核 (依序點選「Lighthouse」>「Options」>「Performance」) (另請參閱「透過 Lighthouse 找出效能改善機會」)。
Lighthouse 會針對延遲擷取的資源,顯示以下的失敗稽核:
- 按下 `Control+Shift+J` 鍵 (在 Mac 上為 `Command+Option+J` 鍵) 開啟開發人員工具。
- 按一下 [網路] 分頁標籤。
main.css
檔案並非由 HTML 文件中的 Link 元素 (<link>
) 擷取,而是由 fetch-css.js
這個個別的 JavaScript 檔案在 window.onLoad
事件後,將 Link 元素附加至 DOM。也就是說,只有在瀏覽器完成剖析及執行 JS 檔案後,才會擷取檔案。同樣地,只有在 CSS 檔案下載完成後,系統才會擷取 main.css
中指定的網路字型 (K2D.woff2
)。
「關鍵要求鏈結」代表瀏覽器優先處理及擷取資源的順序。這個網頁目前的樣貌如下:
├─┬ / (initial HTML file)
└── fetch-css.js
└── main.css
└── K2D.woff2
由於 CSS 檔案位於要求鏈結的第 3 層,Lighthouse 將其視為較晚發現的資源。
預先載入重要資源
main.css
檔案是重要的資產,必須在網頁載入時立即使用。針對這類在應用程式中較晚擷取的重要檔案,請使用連結預先載入標記,在文件標頭中加入 Link 元素,通知瀏覽器提早下載。
為這個應用程式新增預先載入標記:
<head>
<!-- ... -->
<link rel="preload" href="main.css" as="style">
</head>
as
屬性用於識別要擷取的資源類型,而 as="style"
則用於預先載入樣式表檔案。
重新載入應用程式,並查看開發人員工具中的「網路」面板。
請注意,在 JavaScript 負責擷取該檔案之前,瀏覽器擷取 CSS 檔案的方式甚至已完成剖析。透過預先載入功能,瀏覽器會知道要針對資源進行預先擷取,並假設該資源對網頁至關重要。
如果使用方式不當,預先載入可能會對效能造成不利影響,因為系統會對未使用的資源提出不必要的要求。在這個應用程式中,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
,系統也會提出擷取 details.css
的要求。
載入資源後的幾秒內,如果網頁未使用預先載入的資源,Chrome 會在「Console」面板中顯示警告。
您可以利用這項警告做為指標,找出網頁中未立即使用的預先載入資源。您現在可以移除這個網頁中不必要的預先載入連結。
<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>
如要瞭解這會如何觸發檔案要求,請在「DevTools」中開啟「Network」面板,然後取消勾選「Disable cache」選項。
重新載入應用程式,看看在擷取所有其他檔案之後,如何對 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')
結論
透過本程式碼研究室,您應該已充分瞭解如何透過預先載入或預先擷取特定素材資源,改善網站的使用者體驗。請注意,這些技巧不應用於每項資源,且使用方式不當可能會影響效能。只需選擇性地預先載入或預先擷取,即可獲得最佳結果。
摘要:
- 對於較晚發現但對目前網頁至關重要的資源,請使用預先載入。
- 針對日後導覽路徑或使用者動作所需的資源,使用預先擷取。
目前並非所有瀏覽器都支援預先載入和預先擷取。也就是說,並非所有應用程式使用者都能注意到效能提升。
如要進一步瞭解預先載入和預先擷取對網頁的影響,請參閱下列文章: