Web 性能優化:控制關鍵請求的優先級
翻譯自:https://calibreapp.com/blog/critical-request,作者 Ben Schwarz,已獲得作者授權,原文略作中文語境調整。
前言
ByteDance Web Infra 團隊裏面有兩個方向專門關注前端性能,分別從代碼和監控對性能優化有很深入的研究。
性能優化有很多角度,其中一個關鍵是控制關鍵請求的優先級,從而達到性能優化的效果。本文以一種相對系統的方式來進行該方法的探討。也歡迎有興趣的讀者關注我們,和我們進行交流。
構建一個網站服務看似簡單:發送 HTML,瀏覽器識別出接下來需要加載什麼資源。然後,我們耐心的等待頁面就緒。
你不知道的是,這背後發生了很多事情。你有沒有想過,瀏覽器是如何判斷哪些資產需要以什麼順序被請求的?
內容概覽:
-
什麼是資產優先級?
-
Chrome 如何安排資源優先級?
-
什麼樣的請求是關鍵的?
-
Lighthouse 審計:避免關鍵請求的依賴鏈。
-
技術:控制請求優先級。
-
技術:圖片懶加載。
-
技術:font-display
-
關鍵請求檢查清單。
什麼是資產優先級?
現代瀏覽器用流式解析器來解析 HTML —— 在完全下載之前,就可以在 HTML 標記之中找到資產。當瀏覽器找到資產時,就會按照預先確定的優先級把它們加到網絡隊列中。
預先確定的優先級可能是:Lowest, Low, Medium, High 和 Highest 其中之一。通過優先級分配,瀏覽器可以知道哪個請求對頁面快速加載最關鍵。
本文以 Chrome 爲主,但其他瀏覽器對請求的優先級排序也是類似的。你可以在 Chrome、Safari、Firefox 或 Edge 開發者工具中,通過右鍵單擊任何表格標題並選擇 “優先級” 來查看請求優先級。
如何在 Chrome 開發者工具中啓用 “優先級” 列來檢查請求優先級
請求優先級也可以在 Chrome 的 Performance 面板中看到:
如何在 Chrome 開發者工具的 Performance 面板中調查資源的時間和優先級
Chrome 如何安排資源優先級?
資源按出現的順序被添加到網絡隊列中。然後瀏覽器會把網絡活動投入用於儘快獲取到最高優先級的資源。
每種資源類型都有自己的一組規則來決定分配給它的優先級:
什麼樣的請求是關鍵的?
關鍵請求是指顯示在頁面初始視口裏的資源。
這些資源對 Core Web Vitals[2] 中諸如 Largest Contentful Paint(最大內容繪製)[3] 和 First Contentful Paint[4](首次內容繪製)這些指標有着直接的影響。以這篇文章爲例,我們可以直觀地識別出視口需要的資產,以便完全渲染。
對瀏覽者來說至關重要的內容是報頭和文章標題
對於這個頁面來說,關鍵的請求是:
-
HTML
-
CSS
-
LOGO
-
3 個字權重
-
頭條圖片(Largest Contentful Paint 元素)
這些資源(注意,沒有 JavaScript)對於初始視口的視覺展示至關重要。他們應該先被加載。
在審計你的頁面時,我們推薦:
-
對頁面進行可視化審計,注意視口中的關鍵元素。
-
最初的 5 個 HTTP 請求應該是:HTML + 4 個關鍵請求。
-
確保關鍵的請求不要被重定向。
-
更新你的站點,確保關鍵資源是優化過、壓縮過、有緩存能力且有正確的 HTTP 頭的。
Lighthouse 審計:避免關鍵請求的依賴鏈
谷歌的 Lighthouse 套件附帶了一個名爲 “避免關鍵請求的依賴鏈” 的審計,高亮展示了被鏈接在一起的請求。當瀏覽器在發出請求是由於另一個請求引用它時(也稱爲依賴項),我們稱之爲請求鏈。
Lighthouse 避免關鍵請求的依賴鏈審計的例子
關鍵請求鏈最常見的一個例子是,比如某些樣式表內部加載了在初始頁面視口顯示的字體或背景圖像。
@font-face {
font-family: 'Calibre';
font-weight: 400;
font-display: swap;
src: url('/Calibre-Regular.woff2') format('woff2'), url('/Calibre-Regular.woff')
format('woff');
}
.carousel-bg {
background-image: url('/images/main-masthead-bg.png');
}
你可以使用 Lighthouse 的 “避免關鍵請求的依賴鏈” 的審計來診斷和識別出頁面中的資源依賴。
減少關鍵請求鏈的整體數量,有助於更快的 Largest Contentful Paint(最大內容繪製) 和即時的用戶體驗。
爲了減少關鍵請求鏈的影響,請使用以下 Web 性能策略:
-
減少請求的數量
-
使用壓縮和最小化來減少資源的大小
-
將非關鍵腳本標記爲異步
-
考慮將
@font-face
聲明直接內聯到 HTML 中 -
避免使用 CSS 背景圖片或
@import
-
使用預加載提前獲取關鍵資源
-
使用 bundlephobia[5] 尋找該庫的更小替代品
技術:控制請求優先級
請求優先級會被 preload[6] 的使用所影響。預加載的資源會被分配爲高優先級,並且在頁面的初始加載中優先被請求。
<link rel="preload" href="Calibre-Regular.woff2" as="font" crossorigin />
優先級排序前後的 webfont 資產。排序後,以 High 優先級請求字體
使用 preload,相當於告訴瀏覽器:“你可能還不知道它是什麼,但我們需要它。”
預加載有助於優化關鍵請求,但也不要濫用!如果預加載了過多的資源,頁面性能會劣化 [7]。
預加載會影響 Largest Contentful Paint(最大內容繪製) 和 Cumulative Layout Shift[8](累積佈局偏移)。在某些情況下,影響可能是負面的。我們建議使用預加載請求進行試驗,但一定要前後仔細測試。
技術:圖片懶加載
默認情況下,瀏覽器會加載 HTML 中指定的所有圖片,哪怕用戶實際上永遠不會看見的那些。懶加載允許你指定某些圖片只有當用戶滾動頁面到它們附近時纔去請求。如果用戶不滾動頁面,瀏覽器就不會加載這些圖片。
使用這種方法,您可以提高整體渲染速度,並節省不必要的數據傳輸。懶加載是提高 Largest Contentful Paint(最大內容繪製)的有效方法。
過去,我們使用第三方庫或手寫腳本實現懶加載。如今,它已內置在瀏覽器中 [9]。
使用方法如下:
-
在已經知道會出現在視口下方的
<img />
元素上加上loading="lazy"
屬性。 -
當頁面滾動時,懶加載的圖片已經加載完成,準備好展示了。
累積佈局偏移(CLS)標識用戶交互期間的頁面佈局偏移。請確保設置圖像的 width 和 height 屬性,以避免懶加載的圖像在渲染時,頁面重新佈局。
就是這樣!懶加載的實現方法並不複雜,但是對加速渲染非常有幫助。一定要儘可能用上。
技術:font-display
根據 HTTP Archive 中的統計,69% 的站點使用 web 字體 [10]。不幸的是,不幸的是,在大多數情況下,它們提供的體驗都低於標準。
每個人都目睹過字體出現,然後消失,改變了粗細,頁面彷彿被震動了一樣。這些移位現在會被累積佈局移位(CLS)指標所測量。
我們已經證實了用 <link rel="preload" />
控制字體請求的優先級對渲染速度有驚人的影響。所以顯而易見,我們在大部分情況下都應該提高字體請求的優先級。
我們可以用 CSS font-display[11] 進一步提高渲染速度。這個 CSS 屬性允許你控制字體在請求和加載後如何展示。
你可以用
font-display
來優化 Largest Contentful Paint[12](最大內容繪製)和 Cumulative Layout Shift[13](累積佈局偏移)
有五個 font-display 選項 [14] 供您選擇。我們推薦使用 swap
選項,它可以先立即呈現文本,然後在加載網絡字體後立即替換。
給定這樣的字體棧:
body {
font-family: Calibre, Helvetica, Arial;
}
瀏覽器會先用 Helvetica 字體展示(或者 Arial,如果你的系統裏沒有安裝 Helvetica)直到 Calibre 字體加載完成。
沒有 font-display
文字在 HTML、CSS 和網絡字體加載完後才展示:
沒有 font-display
,文本在 2.44 秒顯示。
加上 font-display: swap
文字在 HTML 下載並且處理後立刻顯示了,取得 1.6 秒的進步:
使用 font-display
,文本在 835 毫秒顯示。
font-display
在主流現代瀏覽器裏支持的不錯 [15],你可以從今天開始使用它了。
關鍵請求檢查清單
有了這些知識,您現在應該能夠爲您的站點選擇最關鍵的資產,並相應地對它們進行優先級排序。如果你想進一步推進優先級和速度的優化,請遵循以下清單:
-
啓用 Chrome 開發者工具的 Priority 列。
-
儘可能減少所需的關鍵請求的數量。
-
檢查哪些請求必須在用戶看到完整渲染的頁面之前發出。使用
<link rel="preload" />
對這些關鍵請求進行優先處理。 -
使用 link prefetching[16],優化可能在下一個導航中使用的資源。
-
使用 Link Preload HTTP headers[17] 聲明要在 HTML 完全交付之前預加載的資源。
-
確保圖像尺寸正確的提前寫好。
-
使用內聯 SVG 展示 Logo 和圖標。
-
使用更好的圖像格式,如 AVIF 或 WEBP。
-
使用
font-display: swap
在初始渲染中展示文本。 -
使用壓縮的字體格式,如 WOFF2 或 variable fonts(可變形字體)。
-
在 Chrome://net-internals/#events 中查看 Chrome 的網絡事件。
-
記住:最快的請求,是從未發出的請求。
祝你優化快樂!
參考資料
[1] JavaScript Loading Priorities in Chrome: https://tech.bytedance.net/articles/7025506101156118536#:~:text=JavaScript%20Loading%20Priorities%20in%20Chrome
[2] Core Web Vitals: https://tech.bytedance.net/articles/7025506101156118536#:~:text=%E8%BF%99%E4%BA%9B%E8%B5%84%E6%BA%90%E5%AF%B9-,Core%20Web%20Vitals,-%E4%B8%AD%E8%AF%B8%E5%A6%82%20Largest
[3] Largest Contentful Paint(最大內容繪製): https://web.dev/lcp/
[4] First Contentful Paint: https://tech.bytedance.net/articles/7025506101156118536#:~:text=First%20Contentful%20Paint
[5] 使用 bundlephobia: https://bundlephobia.com/package/moment@2.29.1
[6] preload: https://tech.bytedance.net/articles/7025506101156118536#:~:text=%E4%BC%98%E5%85%88%E7%BA%A7%E4%BC%9A%E8%A2%AB-,preload,-%E7%9A%84%E4%BD%BF%E7%94%A8%E6%89%80
[7] 頁面性能會劣化: https://tech.bytedance.net/articles/7025506101156118536#:~:text=%E8%BF%87%E5%A4%9A%E7%9A%84%E8%B5%84%E6%BA%90%EF%BC%8C-,%E9%A1%B5%E9%9D%A2%E6%80%A7%E8%83%BD%E4%BC%9A%E5%8A%A3%E5%8C%96,-%E3%80%82
[8] Cumulative Layout Shift: https://web.dev/cls/
[9] 內置在瀏覽器中: https://caniuse.com/?search=lazy
[10] 69% 的站點使用 web 字體: https://httparchive.org/reports/state-of-the-web?start=latest#fonts
[11] CSS font-display: https://css-tricks.com/almanac/properties/f/font-display/
[12] Largest Contentful Paint: https://web.dev/lcp
[13] Cumulative Layout Shift: https://web.dev/cls/
[14] 五個 font-display 選項: https://css-tricks.com/almanac/properties/f/font-display/
[15] 支持的不錯: https://caniuse.com/mdn-api_fontface_display
[16] link prefetching: https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ
[17] Link Preload HTTP headers: https://www.w3.org/TR/preload/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/P63LEMaXLMyWGYVdLiWxZw