- 原文地址:Front-End Performance Checklist 2019 — 2
- 原文做者:Vitaly Friedman
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:格子熊
- 校對者:Ivocin,Fengziyin1234
讓 2019 來得更迅速吧~你正在閱讀的是 2019 年前端性能優化年度總結,始於 2016。javascript
[譯] 2019 前端性能優化年度總結 — 第一部分
[譯] 2019 前端性能優化年度總結 — 第二部分
[譯] 2019 前端性能優化年度總結 — 第三部分
[譯] 2019 前端性能優化年度總結 — 第四部分
[譯] 2019 前端性能優化年度總結 — 第五部分
[譯] 2019 前端性能優化年度總結 — 第六部分html
爲了使用戶感受交互流暢,界面的響應時間不得超過 100ms。若是超過了這個時間,那麼用戶將會認爲該應用程序是卡頓的。RAIL,一個以用戶爲中心的性能模型 爲你提供了健康的目標:爲了達到 <100 毫秒的響應,頁面必須在每 50 毫秒內將控制權交還給主線程。預計輸入延遲時間 能夠告訴咱們是否到達了這個閾值,理想狀況下,它應該小於 50 毫秒。對於像動畫這樣的(性能)高壓點,若是能夠,最好不要作任何事情。前端
RAIL, 一個以用戶爲中心的性能模型。vue
此外,每一幀動畫應在 16 毫秒內完成,從而達到每秒 60 幀(1 秒 ÷ 60 = 16.6 毫秒)——最好在 10 毫秒如下。因爲瀏覽器須要時間將新幀繪製到屏幕上,所以你的代碼應在到達 16.6 毫秒的標記以前執行完成。咱們開始討論 120 fps(例如 iPad 的新屏幕以 120Hz 運行),而 Surma 已經覆蓋了一些 120 fps 的 渲染性能解決方案,但這可能不是咱們目前正關注的目標。java
對性能預期持悲觀態度,但要 在界面設計上保持樂觀 並 明智地使用空閒時間 。顯然,這些目標適用於運行時性能,而不是加載性能。react
雖然很難實現,但最好將終級目標定爲,首次繪製時間 1 秒之內,速度指數 的值限制在 1250 如下。因爲基準是模擬在價值 200 美圓的 Android 手機(如 Moto G4)上,網絡爲 slow 3G,400ms RTT 和 400kbps 的傳輸速度,目標是 交互時間低於 5 秒,對於重複訪問,目標是低於 2 秒(只能經過 service worker 實現)。android
請注意,當談到互動指標時,最好區分 First CPU Idle 以及 Time to Interactive ,以免誤解。前者是主要內容渲染後的最先點(其中頁面至少有 5 秒的響應時間)。後者是頁面能夠始終響應輸入的時間。(感謝 Philip Walton !)webpack
咱們有兩個主要限制因素,限制咱們制定一個 合理的 目標來保證網絡內容的快速傳輸。一方面,因爲 TCP 慢啓動,咱們有着網絡傳輸的限制。HTML 的前 14 KB是最關鍵的有效負載塊——而且是第一次往返中惟一能夠提供的預算(因爲手機喚醒時間,這是在 400ms RTT 狀況下 1 秒內得到的)ios
另外一方面,內存和 CPU 有 硬件限制(稍後咱們將詳細討論它們),緣由是 JavaScript 的解析時間。爲了實現第一段中所述目標,咱們必須考慮 JavaScript 關鍵文件大小的預算。關於預算應該是多少有不少不一樣的意見(這應該由你的項目的自己決定),可是 gzip 壓縮後預算爲 170KB 的 JavaScript 已經須要花費 1s 才能在普通手機上進行解析和編譯。假設解壓縮時 170KB 擴展到 3 倍大小,那麼解壓縮後(0.7MB)時,那已經多是 Moto G4 或 Nexus 2 上「用戶體驗的喪鐘」。git
固然,你的數據可能顯示你的客戶沒有使用這些設備,可是也許由於低下的性能致使你的服務沒法訪問,他們根本沒有出如今你的分析中。事實上,Google 的 Alex Russels 建議將 gzip 壓縮後大小爲 130 - 170KB 做爲一個合理的上限,當超出這個預算時,你應該進行慎重考慮。在現實世界中,大多數產品都不是很接近(這個標準);當今的 bundle 平均大小約爲 400KB,與 2015年底相比增加了 35%。在中等水平的移動設備上,Time-To-Interactive 佔 30 - 35 秒。
咱們固然也能夠超過 bundle 的大小預算。例如,咱們能夠根據瀏覽器主線程的活動設置性能預算,即在開始渲染以前進行繪製,或 跟蹤前端 CPU 熱點。Calibre,SpeedCurve 以及 Bundlesize 等工具可以幫你控制預算,而且能夠集成到你的構建過程當中。
此外,性能預算可能不該該是固定值。因爲依賴網絡鏈接,性能預算應該(對不一樣的網絡條件)進行適配,但不管他們如何使用,慢速鏈接上的負載更加「昂貴」。
From Fast By Default: Modern loading best practices by Addy Osmani (幻燈片 19)
性能預算應根據普通移動設備的網絡條件進行調整。(圖片來源:Katie Hempenius) (大圖)
不要過度關注那些炫酷的東西。 堅持你本身的構建環境,不管是 Grunt,Gulp,Webpack,Parcel 仍是工具組合。只要你得到了所需結果,而且構建過程當中沒有任何問題,這就能夠了。
在構建工具中,Webpack 彷佛是最成熟的工具,有數百個插件可用於優化構建大小。入門 Webpack 可能會很難。因此若是你想要入門,這裏有一些很棒的資源:
保持 漸進加強 做爲前端架構和部署的指導原則是一個安全的選擇。首先設計和構建核心體驗,而後使用高級特性爲支持的瀏覽器提高體驗,建立 彈性 體驗。若是你的網站在一臺擁有着差勁網絡、屏幕以及瀏覽器的慢速機器上運行的很快,那麼它在一臺擁有強力網絡和瀏覽器的快速機器上只會運行地更快。
有不少未知因素影響加載——網絡,熱量限制,第三方腳本,緩存替換,解析器阻塞模式,磁盤 I/O,IPC延遲,已安裝的擴展,殺毒軟件和防火牆,後臺 CPU 任務,硬件和內存限制,L2/L3 緩存的差別,RTTS等。JavaScript 的成本最高,此外默認狀況下阻塞渲染的 web 字體以及圖像也常常消耗過多內存。隨着性能瓶頸從服務器轉移到客戶端,做爲開發人員,咱們必須更詳細地考慮全部這些未知因素。
因爲 170KB 的預算已經包含關鍵路徑 HTML/CSS/JavaScript,路由,狀態管理,實用程序,框架和應用程序邏輯,咱們必須完全審覈咱們選擇不一樣框架的網絡傳輸成本,解析/編譯時間和運行時成本。
正如 Seb Markbåge 所指出的,衡量框架啓動成本的一個好方法是首先渲染一個視圖,而後將其刪除後從新渲染,由於它能告訴你框架如何壓縮。首次渲染趨向於喚醒一堆懶洋洋的編譯代碼,一個更大的樹能夠在壓縮時收益。第二次渲染基本上模擬了隨着頁面複雜性的提高,頁面代碼是如何重用影響性能特徵的。
From Fast By Default: Modern Loading Best Practices by Addy Osmani (幻燈片 18, 19).
如今,並不是每一個項目都須要框架,並且不是每一個單頁應用的頁面都須要加載框架。在 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 庫)。可是在艱難的時間表上,在選擇一個選項以前,最好至少考慮大小 + 初始解析時間的總成本;輕量級選項,如 Preact,Inferno, Vue, Svelte 或者 Polymer,均可以很好地完成工做。基線的大小將定義應用程序代碼的約束。
一個很好的起點是爲你的應用程序選擇一個好的默認堆棧。Gatsby.js(React), Preact CLI,以及 PWA Starter Kit 爲中等移動硬件上的快速加載提供了合理的默認值。
(圖片來源: Addy Osmani)(大圖)
不一樣的框架會對性能產生不一樣的影響,而且不須要不一樣的優化策略,所以你必須清楚地瞭解你將依賴的框架的全部細節。構建 Web 應用程序時,請查看 PRPL模式 和 應用程序 shell 體系結構。這個想法很是簡單:推送初始路由交互所需的最少代碼,以便快速渲染,而後使用 service worker 進行緩存和預緩存資源,而後異步地延遲加載所需的路由。
PRPL 表明按需推送關鍵資源,渲染初始路由,預緩存與按需求延遲加載剩餘路由。
應用程序 shell 是驅動用戶界面所須要的最少 HTML,CSS 和 JavaScript。
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)。
REST 和 GraphQL 之間的區別,就如左圖 Redux + REST 之間的對話與右圖 Apollo + GraphQL 的對話的區別(圖片來源:Hacker Noon)(大圖)
根據你的組織的優先級和策略,你可能須要考慮使用 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)。
根據你擁有的動態數據量,你能夠將內容的某些部分「外包」到 靜態站點生成器,將其推送到 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 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。