Netflix 的 Web 效能案例研究
為 Netflix.com 改進桌面端可互動時間
提綱:Web 效能優化沒有銀彈。簡單的靜態網頁得益於使用極少 JavaScript 程式碼的服務端渲染。庫的謹慎使用可以為複雜的頁面帶來巨大的價值。
Netflix 是最受歡迎的視訊流服務之一。自 2016 年在全球推出以來,公司發現許多新使用者不僅通過移動裝置完成註冊,而且還使用了不太理想的網路連線。
通過改進用於 Netflix.com 註冊過程 JavaScript 程式碼和使用預載入技術,開發人員團隊可以為移動和桌面使用者提供更好的使用者體驗,並提供多項改進。
- 減少 50% 的載入和可互動時間(適用於 Netflix.com 桌面端未登入的主頁)
- 通過把 React 和其他客戶端庫改為原生的 JavaScript 使打包大小減少 200 KB。React 仍在服務端使用
- 為將來的操作預獲取 HTML,CSS 和 JavaScript(React)使可互動時間減少 30%
通過嵌入更少的程式碼來減少可互動時間
Netflix 開發者優化效能的地方是未登入主頁,使用者在此頁面註冊並登入站點。
新使用者和已登出使用者的 Netflix.com 主頁
此頁面初始包含 300KB 的 JavaScript 程式碼,其中一些是 React 和其他客戶端程式碼(例如像 Lodash 的工具庫),而且還有一些是必要的上下文資料用來給 React 的狀態注水(hydrate)。
所有 Netflix 的網頁都由服務端 React 渲染,這些頁面為生成的 HTML 和客戶端應用提供服務,因此維持新優化的主頁結構不變和保持開發人員體驗的一致性同樣重要。
Homepage 選項卡是最初使用 React 編寫的元件的示例
使用 Chrome 的 DevTools 和 Lighthouse 來模擬 3G 網路下載入未登入主頁,結果顯示未登入主頁需要 7 秒時間來載入,這段時間對於一個簡單的入口頁面來說實在是太久了,所以我們開始調查改進的可能性。通過一些效能審查,Netflix 發現他們的客戶端 JS 有過高的開銷。
通過 Chrome DevTools 的網路限速功能,檢視未優化的 Netflix.com 的表現。
通過關閉瀏覽器中的 JavaScript 來觀察站點中仍在起作用的元素,開發者團隊可以決定 React 在未登入主頁是否真正必要。
由於頁面中的多數元素是基本的 HTML,剩下的元素比如 JavaScript 點選處理和新增類可以用原生 JavaScript 來替換,而頁面原來使用 React 實現的語言切換器則使用不到 300 行的原生 JavaScript 程式碼重構。
移植到原生 JavaScript 的元件完全列表:
- 基礎互動(主頁中的選項卡)
- 語言切換器
- Cookie 橫幅(針對非美國訪問者)
- 分析用的客戶端日誌
- 效能評估和記錄
- 廣告來源引導程式碼(出於安全考慮,沙盒化放在 iframe 裡)
雖然 React 的初始程式碼僅僅 45 KB,在客戶端移除 React、一些庫和相應的 App 程式碼減少的 JavaScript 程式碼總量超多 200 KB,由此在 Netflix 的未登入主頁降低了超過 50% 的可互動時間。
移除客戶端 React、Lodash 和其他一些庫前後的負載比較。
在實驗環境下,我們可以使用 Lighthouse(trace)快速測驗使用者是否能與 Netflix 主頁互動。結果桌面端的 TTI 少於 3.5s。
可互動時間優化後的 Lighthouse 報告。
那麼這個領域的度量標準呢?使用 Chrome 使用者體驗報告我們可以看到首次輸入延遲 —— 從使用者首次與你的站點互動時間到瀏覽器真正響應那次互動的時間 —— 對於 97% 的 Netflix 桌面使用者來說很快。結果非常棒。
首先輸入延遲(FID)度量使用者在與頁面互動時的延遲體驗。
為後續頁面預載入 React
為了進一步提高瀏覽登入主頁的效能,Netflix 利用使用者在入口頁面上花費的時間針對可能會登入的下一個頁面進行資源預載入。
通過兩項技術完成 —— 內建的 <link rel=prefetch>
瀏覽器 API 和 XHR 預載入。
內建的瀏覽器 API 包含頁面頭部標籤內的簡單連結標籤。它會建議瀏覽器資源(例如 HTML、JS、CSS、圖片)可以被預載入,雖然它並不保證瀏覽器真的會預載入資源,並且它缺少其他瀏覽器的全面支援。
預載入技術對比
另一方面,XHR 預載入已經成為瀏覽器標準很多年了,當 Netflix 團隊提示瀏覽器快取資源時,其成功率達到 95%。但是 XHR 預載入不能預載入 HTML 文件,Netflix 用它來為後續頁面預載入 JavaScript 和 CSS 打包檔案。
注意:Netflix 配置的 HTTP 響應頭禁止使用 XHR 快取 HTML(它們確實不快取(no-cache)第二個頁面的 HTML)。連結預載入會按預期工作,因為它對 HTML 有效,即使設定了不快取(no-cache)。
// 建立新的 XHR 請求
const xhrRequest = new XMLHttpRequest();
// open the request for the resource to "prefetch"
// 開啟請求來“預載入”資源
xhrRequest.open(`GET`, `../bundle.js`, true);
// 傳送!
xhrRequest.send();
複製程式碼
通過使用瀏覽器內建 API 和 XHR 預載入 HTML、CSS 和 JS,可互動時間減少了 30%。這個實現不需要重寫 JavaScript,也不會對未登入主頁的效能造成負面影響,而且從此以後,能以極低的風險為提升頁面效能提供了非常有價值的工具。
預載入實現之後,Netflix 開發者可以通過分析頁面減少的可互動時間資料來觀察效能提升效果,同樣使用 Chrome 開發工具直接度量資源快取的命中情況。
Netflix 未登入主頁 —— 優化總結
通過預載入 Netflix 未登入主頁資源和優化客戶端程式碼,Netflix 可以在註冊過程中出色地提升可互動時間指標。通過使用瀏覽器內建 API 和 XHR 預載入來預獲取未來頁面,Netflix 可以把可互動時間降低 30%。這是針對下一頁面的載入,其中包含單頁應用註冊過程的引導程式碼。
Netflix 團隊進行的程式碼優化表明,React 是一個十分有用的庫,不過它可能無法為每個問題提供足夠的解決方案。通過從第一個用於註冊的入口頁面的客戶端程式碼中刪除 React,可互動時間減少了 50% 以上。縮短客戶端上的可互動時間還可以讓使用者以更快地速度單擊註冊按鈕,這表明程式碼優化完全可以帶來更好的使用者體驗。
雖然 Netflix 沒有在主頁中使用 React,但他們為後續的頁面預載入。這使得他們整個頁面應用程式流程中的其他部分可以利用客戶端 React。
更多關於這些優化的細節,請觀看 Tony Edwards 的出色演講:
- YouTube 視訊連結:youtu.be/V8oTJ8OZ5S0
總結
通過密切關注 JavaScript 的開銷,Netflix 發現了改善可互動時間的機會。若想發現你的站點是否有機會在這點上做得更好,可以藉助你的效能工具。
Netflix 決定做出的權衡是使用 React 對入口頁面進行伺服器渲染,同時也在其上預先獲取 React 和其餘註冊流程的程式碼。這樣可以優化首次載入效能,同時還可以優化其餘註冊流的載入時間,因為它是一個單頁應用程式,因此需要下載更大的 JS 打包檔案。
考慮一下是否使用原生 JavaScript 是否適合你的站點的流程。如果你確實需要使用庫,那麼嘗試只嵌入你的使用者需要的程式碼。預載入技術可以幫助優化未來瀏覽頁面的載入時間。
補充說明:
- Netflix 考慮過使用 Preact,但是對於低互動性的簡單頁面流而言,使用原生 JavaScript 是一個更簡單的選擇。
- Netflix 試驗過使用 Service Workers 進行靜態資源快取。那時 Safari 不支援這個 API(現在支援了),但他們現在又在探索這個了。Netflix 的註冊過程更多需要的是較舊的瀏覽器支援而不是會員體驗。許多使用者都會在較舊的瀏覽器上註冊,但會在其原生移動應用或電視裝置上觀看 Netflix。
- Netflix 的入口頁面極為動態。這是他們的註冊過程中進行 A/B 測試最多的頁面,機器學習模型用於根據位置、裝置型別和許多其他因素定製訊息和影像。支援近 200 個國家,每個派生頁面都面對著不同的本地化、法律和價值資訊挑戰。有關 A/B 測試的更多資訊,請參閱 Ryan Burgess 的測試,只為更好的使用者體驗。
感謝 Netflix UI 工程師,Tony Edwards、Ryan Burgess、Brian Holt、Jem Young、Kristofer Baxter(Google)、Nicole Sullivan(Chrome)和 Houssein Djirdeh(Chrome)的審閱和貢獻。
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。