[譯] 2019 前端效能優化年度總結 — 第二部分

格子熊發表於2019-01-22

讓 2019 來得更迅速吧~你正在閱讀的是 2019 年前端效能優化年度總結,始於 2016。

[譯] 2019 前端效能優化年度總結 — 第一部分
[譯] 2019 前端效能優化年度總結 — 第二部分
[譯] 2019 前端效能優化年度總結 — 第三部分
[譯] 2019 前端效能優化年度總結 — 第四部分
[譯] 2019 前端效能優化年度總結 — 第五部分
[譯] 2019 前端效能優化年度總結 — 第六部分

設定切實可行的目標

7. 100 毫秒響應時間,60 fps

為了使使用者感覺互動流暢,介面的響應時間不得超過 100ms。如果超過了這個時間,那麼使用者將會認為該應用程式是卡頓的。RAIL,一個以使用者為中心的效能模型 為你提供了健康的目標:為了達到 <100 毫秒的響應,頁面必須在每 50 毫秒內將控制權交還給主執行緒。預計輸入延遲時間 可以告訴我們是否到達了這個閾值,理想情況下,它應該小於 50 毫秒。對於像動畫這樣的(效能)高壓點,如果可以,最好不要做任何事情。

RAIL

RAIL, 一個以使用者為中心的效能模型。

此外,每一幀動畫應在 16 毫秒內完成,從而達到每秒 60 幀(1 秒 ÷ 60 = 16.6 毫秒)——最好在 10 毫秒以下。由於瀏覽器需要時間將新幀繪製到螢幕上,因此你的程式碼應在到達 16.6 毫秒的標記之前執行完成。我們開始討論 120 fps(例如 iPad 的新螢幕以 120Hz 執行),而 Surma 已經覆蓋了一些 120 fps 的 渲染效能解決方案,但這可能不是我們目前正關注的目標。

對效能預期持悲觀態度,但要 在介面設計上保持樂觀明智地使用空閒時間 。顯然,這些目標適用於執行時效能,而不是載入效能。

8. 速度指數 < 1250,TTI(互動時間) < 5s(3G),關鍵檔案大小 < 170KB(gzip 壓縮後)

雖然很難實現,但最好將終級目標定為,首次繪製時間 1 秒以內,速度指數 的值限制在 1250 以下。由於基準是模擬在價值 200 美元的 Android 手機(如 Moto G4)上,網路為 slow 3G,400ms RTT 和 400kbps 的傳輸速度,目標是 互動時間低於 5 秒,對於重複訪問,目標是低於 2 秒(只能通過 service worker 實現)。

請注意,當談到互動指標時,最好區分 First CPU Idle 以及 Time to Interactive ,以避免誤解。前者是主要內容渲染後的最早點(其中頁面至少有 5 秒的響應時間)。後者是頁面可以始終響應輸入的時間。(感謝 Philip Walton !

我們有兩個主要限制因素,限制我們制定一個 合理的 目標來保證網路內容的快速傳輸。一方面,由於 TCP 慢啟動,我們有著網路傳輸的限制。HTML 的前 14 KB是最關鍵的有效負載塊——並且是第一次往返中唯一可以提供的預算(由於手機喚醒時間,這是在 400ms RTT 情況下 1 秒內獲得的)

另一方面,記憶體和 CPU 有 硬體限制(稍後我們將詳細討論它們),原因是 JavaScript 的解析時間。為了實現第一段中所述目標,我們必須考慮 JavaScript 關鍵檔案大小的預算。關於預算應該是多少有很多不同的意見(這應該由你的專案的本身決定),但是 gzip 壓縮後預算為 170KB 的 JavaScript 已經需要花費 1s 才能在普通手機上進行解析和編譯。假設解壓縮時 170KB 擴充套件到 3 倍大小,那麼解壓縮後(0.7MB)時,那已經可能是 Moto G4 或 Nexus 2 上“使用者體驗的喪鐘”。

當然,你的資料可能顯示你的客戶沒有使用這些裝置,但是也許因為低下的效能導致你的服務無法訪問,他們根本沒有出現在你的分析中。事實上,Google 的 Alex Russels 建議將 gzip 壓縮後大小為 130 - 170KB 作為一個合理的上限,當超出這個預算時,你應該進行慎重考慮。在現實世界中,大多數產品都不是很接近(這個標準);當今的 bundle 平均大小約為 400KB,與 2015年末相比增長了 35%。在中等水平的移動裝置上,Time-To-Interactive 佔 30 - 35 秒。

我們當然也可以超過 bundle 的大小預算。例如,我們可以根據瀏覽器主執行緒的活動設定效能預算,即在開始渲染之前進行繪製,或 跟蹤前端 CPU 熱點CalibreSpeedCurve 以及 Bundlesize 等工具能夠幫你控制預算,並且可以整合到你的構建過程中。

此外,效能預算可能不應該是固定值。由於依賴網路連線,效能預算應該(對不同的網路條件)進行適配,但無論他們如何使用,慢速連線上的負載更加“昂貴”。

From 'Fast By Default: Modern Loading Best Practices' by Addy Osmani

From Fast By Default: Modern loading best practices by Addy Osmani (幻燈片 19)

[譯] 2019 前端效能優化年度總結 — 第二部分

效能預算應根據普通移動裝置的網路條件進行調整。(圖片來源:Katie Hempenius) (大圖)

定義環境

9. 選擇並設定你的構建工具

不要過分關注那些炫酷的東西。 堅持你自己的構建環境,無論是 Grunt,Gulp,Webpack,Parcel 還是工具組合。只要你獲得了所需結果,並且構建過程中沒有任何問題,這就可以了。

在構建工具中,Webpack 似乎是最成熟的工具,有數百個外掛可用於優化構建大小。入門 Webpack 可能會很難。所以如果你想要入門,這裡有一些很棒的資源:

10. 預設使用漸進增強

保持 漸進增強 作為前端架構和部署的指導原則是一個安全的選擇。首先設計和構建核心體驗,然後使用高階特性為支援的瀏覽器提升體驗,建立 彈性 體驗。如果你的網站在一臺擁有著差勁網路、螢幕以及瀏覽器的慢速機器上執行的很快,那麼它在一臺擁有強力網路和瀏覽器的快速機器上只會執行地更快。

11. 選擇一個高效能基準

有很多未知因素影響載入——網路,熱量限制,第三方指令碼,快取替換,解析器阻塞模式,磁碟 I/O,IPC延遲,已安裝的擴充套件,防毒軟體和防火牆,後臺 CPU 任務,硬體和記憶體限制,L2/L3 快取的差異,RTTS等。JavaScript 的成本最高,此外預設情況下阻塞渲染的 web 字型以及影象也經常消耗過多記憶體。隨著效能瓶頸從伺服器轉移到客戶端,作為開發人員,我們必須更詳細地考慮所有這些未知因素。

由於 170KB 的預算已經包含關鍵路徑 HTML/CSS/JavaScript,路由,狀態管理,實用程式,框架和應用程式邏輯,我們必須徹底稽核我們選擇不同框架的網路傳輸成本,解析/編譯時間和執行時成本

正如 Seb Markbåge 所指出的,衡量框架啟動成本的一個好方法是首先渲染一個檢視,然後將其刪除後重新渲染,因為它能告訴你框架如何壓縮。首次渲染趨向於喚醒一堆懶洋洋的編譯程式碼,一個更大的樹可以在壓縮時收益。第二次渲染基本上模擬了隨著頁面複雜性的提升,頁面程式碼是如何重用影響效能特徵的。

'Fast By Default: Modern Loading Best Practices' by Addy Osmani

From Fast By Default: Modern Loading Best Practices by Addy Osmani (幻燈片 18, 19).

12. 評估每個框架以及它們的依賴項

現在,並非每個專案都需要框架,而且不是每個單頁應用的頁面都需要載入框架。在 Netflix 的案例中,“刪除 React,幾個庫以及對應的客戶端程式碼將 JavaScript 總量減少了 200KB 以上,導致 Netflix 登出主頁的互動時間縮短了 50% 以上。”然後,團隊利用使用者在目標網頁上花費的時間為使用者可能使用的後續網頁預讀取 React(詳情請繼續閱讀)。

這聽起來很明顯但是值得一提:一些專案也可以從完全刪除現有框架中收益。一旦選擇了一個框架,你將至少使用它好幾年,所以如果你需要使用它,請確保你的選擇得到了充分的考慮

Inian Parameshwaran 測量了排名前 50 的框架的效能足跡(針對首次內容渲染——從導航到瀏覽器從 DOM 渲染第一部分內容的時間)。Inian 發現,單獨來說,Vue 和 Preact 是最快的——無論是桌面端還是移動端,其次是 React(幻燈片)。你可以檢查你的候選框架和它建議的體系結構,並研究大多數解決方案如何執行,例如平均而言,使用服務端渲染或者客戶端渲染。

基線效能成本很重要。根據 Ankur Sethi 的一項研究,“無論你對它的優化程度如何,你的 React 應用程式在印度的普通手機上的載入時間絕對不會低於 1.1 秒。你的 Angular 應用程式始終需要至少 2.7 秒才能啟動。你的 Vue 應用程式的使用者需要等待至少 1 秒才能開始使用它。”無論如何,你可能不會講印度定位為主要市場,但是網路不佳的使用者在訪問你的網站是會獲得類似的體驗。作為交換,你的團隊當然可以獲得可維護性和開發人員效率。但這種考慮值得商榷。

你可以通過探索功能,可訪問性,穩定性,效能,包生態系統,社群,學習曲線,文件,工具,跟蹤記錄,團隊來評估 Sacha Greif 的12 點量表評分系統 中的框架(或者任何其他 JavaScript 庫)。但是在艱難的時間表上,在選擇一個選項之前,最好至少考慮大小 + 初始解析時間的總成本;輕量級選項,如 PreactInfernoVueSvelte 或者 Polymer,都可以很好地完成工作。基線的大小將定義應用程式程式碼的約束。

一個很好的起點是為你的應用程式選擇一個好的預設堆疊。Gatsby.js(React), Preact CLI,以及 PWA Starter Kit 為中等移動硬體上的快速載入提供了合理的預設值。

JavaScript processing times in 2018 by Addy Osmani

(圖片來源: Addy Osmani)(大圖)

13. 考慮使用 PRPL 模式以及應用程式 shell 架構

不同的框架會對效能產生不同的影響,並且不需要不同的優化策略,因此你必須清楚地瞭解你將依賴的框架的所有細節。構建 Web 應用程式時,請檢視 PRPL模式應用程式 shell 體系結構。這個想法非常簡單:推送初始路由互動所需的最少程式碼,以便快速渲染,然後使用 service worker 進行快取和預快取資源,然後非同步地延遲載入所需的路由。

PRPL Pattern in the application shell architecture

PRPL 代表按需推送關鍵資源,渲染初始路由,預快取與按需求延遲載入剩餘路由。

Application shell architecture

應用程式 shell 是驅動使用者介面所需要的最少 HTML,CSS 和 JavaScript。

14. 你是否優化了各個 API 的效能?

API 是應用程式通過所謂的端點向內部和第三方應用程式公開資料的通訊通道。在 設計和構建 API 時,我們需要一個合理的協議來啟動伺服器和第三方請求之間的通訊。Representational State Transfer (REST) 是一個合理的成熟選擇:它定義了開發人員遵循的一組約束,以便以高效能,可靠和可擴充套件的方式訪問內容。符合 REST 約束的 Web 服務稱為 RESTful Web 服務

HTTP 請求成功時,當從 API 檢索資料,伺服器響應中的任何延遲都將傳播給終端使用者,從而延遲渲染。當資源想要從 API 檢索某些資料時,它將需要從相應的端點請求資料。從多個資源渲染資料的元件(例如,在每個評論中包含評論和作者照片的文章)可能需要多次往返伺服器以在渲染之前獲取所有資料。此外,通過 REST 返回的資料量通常大於渲染該元件所需的資料量。

如果許多資源需要來自 API 的資料,API 可能會成為效能瓶頸。GraphQL 為這些問題提供了高效能的解決方案。本身,GraphQL 是 API 的查詢語句,是一個使用你為資料定義的型別系統執行查詢的服務端執行時。與 REST 不同,GraphQL 可以在單個請求中檢索所有資料,並且響應將完全符合要求,而不會像 REST 那樣過多過少讀取資料。

此外,由於 GraphQL 使用 schema(描述資料結構的後設資料),它已經可以將資料組織到首選結構中,因此,例如,使用 GraphQL,我們可以刪除用於處理狀態管理的 JavaScript 程式碼,生成更簡潔的應用程式程式碼,可以在客戶端上執行得更快。

如果你想開始使用 GraphQL,Eric Bear 在 Smashing 雜誌上發表了兩篇精彩的文章:A GraphQL Primer: Why We Need A New Kind Of API 以及 A GraphQL Primer: The Evolution Of API Design (感謝提示,Leonardo)。

Hacker Noon

REST 和 GraphQL 之間的區別,就如左圖 Redux + REST 之間的對話與右圖 Apollo + GraphQL 的對話的區別(圖片來源:Hacker Noon)(大圖

15. 你會使用 AMP 或 Instant Articles 嗎?

根據你的組織的優先順序和策略,你可能需要考慮使用 Google 的 AMP 或者 Facebook 的 Instant Articles 或者 Apple 的 Apple News。如果沒有它們,你也獲得良好的效能,但 AMP 確實提供了一個可靠的效能框架和免費的內容分發網路(CDN),而 Instant Articles 將提高你在 Facebook 上的可見性和效能。

對於使用者來說, 這些技術最直觀的的好處是保證了效能。 所以比起“正常“的和可能膨脹的頁面,有時使用者甚至更喜歡 AMP/Apple News/Instant Pages 連結。對於處理大量第三方內容的內容繁重的網站,這些選項可能有助於大幅加快渲染時間。

除非他們不這樣做。例如,根據 Tim Kadlec的說法,“AMP 文件往往比同行更快,但並不一定意味著頁面具有高效能。在效能方面,AMP 不是最大的差異。”

站長的好處顯而易見:這些格式在各自平臺上的可發現性以及搜尋引擎的可見性提高。你也可以通過重複使用 AMP 作為 PWA 的資料來源來構建漸進式 web APM。至於缺點?顯然,因為各個平臺的不同的要求和限制,開發人員需要對他們的內容,在不同平臺製作和維護不同的版本,如果是 Instant Articles 和 Apple News 沒有實際的URL(感謝 Addy,Jeremy)。

16. 明智地選擇你的 CDN

根據你擁有的動態資料量,你可以將內容的某些部分“外包”到 靜態站點生成器,將其推送到 CDN 並從中提供靜態版本,從而避免資料庫請求。你甚至可以選擇基於 CDN 的靜態託管平臺,通過互動式元件豐富你的頁面作為增強功能(JAMStack)。事實上,其中一些生成器(如 Reats 之上的 Gatsby)實際上是網站編譯器,提供了許多自動優化功能。隨著編譯器隨著時間的推移新增優化,編譯後的輸出隨著時間的推移變得越來越小,越來越快。

請注意,CDN 也可以提供(和解除安裝)動態內容。因此,不必將CDN限制為只有靜態檔案。仔細檢查你的 CDN 是否執行壓縮和轉換(例如,在格式,壓縮和邊緣大小調整方面的影象優化),對 servers workers 的支援,包括邊緣,在 CDN 邊緣組裝頁面的靜態和動態部分(即最接近使用者的伺服器)和其他任務。

注意:基於 Patrick Meenan 和 Andy Davies 的研究,HTTP/2 在許多 CDN 上被破壞,所以我們不應該對那裡的效能提升過於樂觀。

[譯] 2019 前端效能優化年度總結 — 第一部分
[譯] 2019 前端效能優化年度總結 — 第二部分
[譯] 2019 前端效能優化年度總結 — 第三部分
[譯] 2019 前端效能優化年度總結 — 第四部分
[譯] 2019 前端效能優化年度總結 — 第五部分
[譯] 2019 前端效能優化年度總結 — 第六部分

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章