2020前端性能優化清單(一)


2020前端性能優化清單(一)

轉發鏈接:https://mp.weixin.qq.com/s/d9J-_aF9K8QTUtemol-EfQ

簡介

讓2020年變得更...快些吧! 這是一份年度前端性能優化清單,包含了當下創建web快速體驗所需的一切。這份清單自2016年開始已經持續更新了5年。這份清單得到了LogRocket的大力支持,LogRocket是一個前端性能監視解決方案,可幫助重現錯誤並更快地解決問題。

web性能是一頭狡猾的野獸讓人難以琢磨和處理,不是嗎? 我們如何才能知道我們在性能方面所處的真正水平,以及我們的性能瓶頸到底是什麼呢? 它是巨大的JavaScript文件、緩慢的Web字體傳輸、繁重的圖像、還是緩慢的渲染? 是否值得去研究 Tree-Shaking、作用域提升、代碼拆分,以及所有奇特的加載模式,包括交叉點觀察器做懶加載、服務器推送、客戶端提示、HTTP/2、service workers 或者說 edge workers? 而且,最重要的是,我們該從哪裡開始做性能優化,以及我們應該如何建立長期的關注性能的團隊文化?

在過去,性能往往在開發初期時被忽略。性能優化通常會推遲到項目快結束時候,並最終簡單歸結為代碼壓縮,並行請求,靜態資源化,或許還有一些對服務器config文件的微調。現在看來,性能優化這項工作已經發生了很大的變化。

性能不僅僅是一個技術上的問題:它會影響從 可訪問性、可用性到搜索引擎優化的方方面面,並且如果我們把性能優化引入工作流程中,那麼在設計和決策時就需要考慮對性能影響。性能必須不斷地進行測量,監視和完善,但是網絡的日益複雜性帶來了新的挑戰:那就是性能指標的跟蹤,因為性能指標會因設備,瀏覽器,協議,網絡類型和網絡延遲不同而有很大差異(CDN,ISP,緩存,代理,防火牆,負載均衡和服務器配置都對web性能有著明顯的影響)。

因此,如果我們要建立了一個包含性能優化所有要點的清單(從研發開始到網站最終上線),該清單會是什麼樣的呢? 您會在下面找到一份(希望它是沒有偏見的和客觀的)** 2020年前端性能優化清單** — 它包含您可能需要考慮性能的場景和優化手段的簡介,以達到快速的響應時間,流暢的用戶互動,以及網站不會浪費用戶的帶寬。

內容目錄

  • 準備工作:計劃和指標
  • 選擇正確的指標
  • 定義環境
  • 靜態資源優化
  • 構建優化
  • 傳輸優化
  • 網絡與HTTP/2
  • 測試和監控
  • 速成方案
  • 下載清單(PDF,Apple Pages,MS Word)
  • 出發吧!

《 》

《 》

準備工作:計劃和指標

時不時的小優化對於保持良好性能很有效果,但更重要的是:在頭腦中明確性能目標(可衡量的目標),因為這將影響整個開發過程中我們所做的任何決策。下面有幾種不同的性能指標模型,關於這些模型的討論會比較主觀--您只要確保在工作開始時設置自己的優先級即可。

01 建立性能優化的文化

在許多團隊中,前端開發工程師都明確地知道那些常見的性能問題,以及使用何種加載方式能夠解決這些問題。但是因為缺乏對性能優化關注的文化,每一項關於性能的決策都演變成了部門時間的PK,把組織分裂成1一個個孤島。隨著時候您就需要業務方的支持,如何獲取支持呢?首先需要進行一個案例研究,或使用

Performance API[2]證明[3]性能如何提升他們關心的工作指標和關鍵績效指標(KPI)。

如果開發/設計團隊與業務/營銷團隊之間無法對性能優化的目標保持一致,那性能優化將無法長期維持。因此性能優化的工作需要關注客戶服務和銷售團隊的常見投訴,研究高跳出率和低轉化率的原因。探索性能優化如何幫助緩解這些常見問題,並根據與你交談的利益方調整你的論點[4]

運行性能實驗並測量結果 - 無論是在移動設備上還是在桌面上(例如,使用Google Analytics) 將幫助你用真實的數據為公司進行定製性的分析。此外,使用發佈在WPO Stats[5]上的研究案例和實驗數據,也可以幫助我們明確性能對業務提升的重要性,以及它對用戶體驗和業務指標的影響。 然而,僅僅說明性能很重要是不夠的 - 您還需要建立一些可衡量和可跟蹤的目標,並隨著持續跟蹤相關指標。

怎麼達到目標呢? Allison McKnight在她關於建立長期的性能優化文化[6]的演講中,分享了一個全面的案例研究-如何幫助Etsy建立重視性能的公司文化(

幻燈片[7])。 最近,Tammy Everts也談到了在小型和大型組織中如何在團隊中培養關注性能的氛圍[8]

2020前端性能優化清單(一)

Performance budget builder by Brad Frost and Jonathan Fielding’s Performance Budget Calculator can help you set up your performance budget and visualize it. (Large preview)

由Brad Frost的性能預算生成器和Jonathan Fielding的性能預算計算器可以幫助您設置性能預期並對其進行可視化。

02 目標:比你最快的競爭對手至少快20%

根據用戶心理學研究[9],如果想讓用戶感覺你的web網站比其它競品快,那您必須比它們快20%以上。研究您的主要競爭對手,收集它們在移動設備和臺式機上的性能指標,並設置閾值以幫助您超越競爭對手。但是,要獲取準確的性能指標並制定目標,請務必先通過研究分析來全面瞭解用戶體驗。然後,你可以根據90%的主要用戶的反饋和經驗來模擬測試。

你可以使用Chrome UX Report[10] (也叫CrUX, 一個現成的實際用戶體驗監控報告, 參考Ilya Grigorik的視頻介紹[11] 和 Rick Viscomi的詳情使用指南[12])或者Treo網站[13],一個由Chrome UX報告提供支持的實際用戶分析監視工具。作為替代品,你也可以使用Speed Scorecard[14] (也提供對網站收入影響的評估)

Real User Experience Test Comparison[15] 或者SiteSpeed CI[16] (基於綜合測試)。

2020前端性能優化清單(一)

Treo Sites provides competitive analysis based on real-world data. (Large preview)

Treo Sites 根據實際數據提供網站競爭性分析

: 如果你使用Page Speed[17] Insights或者Page Speed Insights API[18]。除了彙總數據,您也可以獲取特定頁面的CrUX性能數據。這些數據對於為 "落地頁" 或 "產品列表" 之類的頁面單獨設置性能目標可能更有用。 補充說明,如果您使用CI來測試性能預期,則需要確保您的測試環境與CrUX匹配,然後在使用CrUX設置性能目標(感謝Patrick Meenan反饋!)。

如果您想知道顯示速度優先級排序背後的原因,或者您想要可視化來展示頁面轉換率下降、跳出率增加後者性能降低,或者您可能需要在組織中倡導基於真實用戶體驗的解決方案,Sergey Chernyshev已經開發[19](UX Speed Calculator)UX 速度計算器[20](一個開源工具),可以幫助你擬合數據並將其可視化,驗證你的觀點。

2020前端性能優化清單(一)

Just when you need to make a case for performance to drive your point across: UX Speed Calculator visualizes an impact of performanc on bounce rates, conversion and total revenue — based on real data. (Large preview)

在需要提高性能來說明您的觀點時:UX 速度計算器基於真實數據,可以把性能對頁面轉化率、跳出率和總收入的影響用可視化的圖標展示

收集數據,建立表格,以提升20%的性能設定你的目標(性能預算)。現在你有了可以衡量的目標來測試了。如果你把預算記在心裡,試著把最小的有效載荷降下來,以獲得一個快速的可交互時間,這樣就是一個正確的性能優化方式。

需要一些資源來開始?

  • Addy Osmani寫了一篇非常詳細的文章,內容包括如何開始做性能預算[21],如何量化新功能的影響,以及當你超出預算時從哪裡開始優化
  • Lara Hogan關於如何在性能預算下進行設計的指南[22]可以為設計師提供有用的指導
  • Harry Roberts發佈了一份指南[23],介紹如何使用Request Map(請求地圖)[24]設置Google工作表,以顯示第三方腳本對性能的影響

Jonathan Fiding的Performance Budget Calculator(性能預算計算器)[25]、Katie Hempenius的Performance Budget Calculator(性能預算計算器)[26]Browser Calories(“瀏覽器卡路里計算”)[27]可以幫助創建性能預算(感謝Karolina Szczur[28]反饋)。

此外,可以設置帶有報告構建大小的圖形的儀表板,使性能預算和當前性能變得可視化。有許多工具可以實現:SiteSpeed.io儀表板[29](開源)、SpeedCurve[30]Calibre[31]只是其中的一小部分,您可以在Perform.rocks[32]上找到更多工具。

一旦有了性能預算,就可以將它們與Webpack性能提示和Bundlesize[33]、Lighthouse CI、PWMetrics[34]Sitespeed CI[35]結合到構建過程中,這樣就可以在git合併請求(pull requests)時考慮性能預算,並在PR評論中提供評分歷史。

要向整個團隊公開性能預算,可以

通過Lightwallet在Lighthouse中集成性能預算[36],或者使用LHCI動作來快速集成到 Github Actions[37]。如果需要自定義,可以使用WebPagetest -chart-API[38],這是一個接口API,用於根據WebPagetest結果構建圖表。

不過,性能意識不應該僅僅來自性能預算。就像Pinterest(世界上最大的圖片社交分享網站)一樣,您可以創建一個自定義eslint規則[39],比如不允許導入依賴關係較重且會使構建產物明顯膨脹的文件或目錄。設置一個在整個團隊中共享的"放心使用"表列表。

此外,還要考慮對您的業務最關鍵的用戶操作。研究、討論和定義關鍵操作的可接受時間閾值,並建立整個組織認可的“UX Ready”用戶計時標記。在許多情況下,用戶瀏覽和行為路徑將涉及許多不同部門的工作,因此,根據可接受的時間進行調整將有助於支持或減少以後團隊和部門間關於性能的討論。確保增加資源和功能的額外性能成本是可見的和理解的。

另外,就像 Patrick Meenan 所建議的,在UX設計過程中就權衡加載順序非常有用。如果您一早就確定頁面中哪些組件比較關鍵,並定義它們應該出現的順序,那就可以確定哪些組件可以延遲加載的。理想情況下,該順序還將影響CSS和JavaScript導入的順序,因此在構建過程中處理它們的順序會變得更加容易。此外,在加載頁面時(例如,當網頁字體尚未加載時),請考慮在“中間”狀態下的視覺體驗應該是什麼。

規劃、規劃、規劃。在早期進行快速的“容易夠得著的水果”似的性能優化可能很誘人,也是一個能快速取得成功的好策略,但是如果沒有規劃,沒有切合實際的、為公司量身定製的性能目標,在長期的開發維護過程中就很難一直把性能放在首位。

首次渲染、首次有內容渲染、首次有效渲染、渲染完成時間和可交互時間之間的區別[40]@denar90

2020前端性能優化清單(一)

11-metrics-front-end-performance-checklist-2020

2020年初,新的性能指標將在Lighthouse v6中發佈。不再推薦使用“首次有效渲染(FMP)”,並且在下個Lighthouse版本中引入最大內容渲染時間(LCP)和總阻塞時間(TBT)這兩個指標。

03 選擇正確的指標

並不是所有的指標都同樣重要[41]。研究哪些指標對您的應用程序最重要:通常,它將由開始呈現界面中最重要的像素的速度以及為這些呈現的像素提供輸入響應的速度來定義。下面這些知識將為您提供最佳的優化目標,以進行不斷的正確方向的努力。再強調一點,定義體驗的指標不是客戶端加載時間,也不是服務器響應時間,而是實際用戶感覺界面有多快。

什麼意思? 與其關注整個頁面加載時間(例如,通過onLoad和DOMContentLoaded計時),不如按照用戶的看法確定頁面加載的優先級。這意味著你會著關注一組略有不同的指標。事實上,選擇正確的指標是持續不斷的過程。

根據Tim Kadlec的研究和Marcos Iglesias在他的演講[42]中的筆記,傳統的度量指標可以分成幾組。通常,我們需要所有這些度量指標才能全面瞭解性能,但是根據您的特定情況,其中一些指標可能比其他更重要。

  • 基於數量的指標: 測量請求的數量、權重和性能分數。這對於隨時間做監控和警報很有幫助,但對於理解用戶體驗來說不夠完美。
  • 里程碑式的指標:在加載過程的生命週期中使用狀態來度量,例如,第一個字節到達瀏覽器的時間、可交互的時間。這些指標很適合描述用戶體驗和監控,但不太適合瞭解各個里程碑之間發生的事情。
  • 渲染的指標: 提供對內容渲染速度的估計(例如,開始渲染時間,速度指數)。對於度量和調整渲染性能很好,但是在度量重要內容的出現時間和可交互時間方面,這些指標就不太好用了。
  • 自定義的指標: 對用戶的特定自定義事件的度量,例如Twitter中首次Tweet渲染時間[43]和Pinterest的PinnerWaitTime[44]。對於精確地描述用戶體驗來說很好,但是對於度量標準和與競爭對手的比較來說就不那麼好了。

為了使性能指標這塊拼圖更完整,我們會在所有這些組中尋找有用的指標。通常,最具體和最相關的是:

  • Time to Interactive[45] (TTI)佈局已經穩定、關鍵的Web字體可見、並且主線程已經空閒下來可以處理用戶輸入的時間點-基本上就是用戶可以與UI交互的時間標記。這是瞭解用戶必須經歷多少等待才能毫無延遲地使用網站的關鍵指標。
  • First Input Delay[46] (FID), 或者 Input responsiveness從用戶首次與網站進行交互到瀏覽器實際上能夠響應該交互的時間。它很好地補充了TTI指標缺少的那部分:當用戶實際與站點進行交互時會發生什麼。 一般僅用作RUM度量標準。有一個標準的JavaScript庫[47],用於在瀏覽器中測量FID。
  • Largest Contentful Paint[48] (LCP)這是在頁面加載時間線中,標記已加載頁面重要內容的時間點。假設頁面中最重要的元素是在用戶的視區中可見的最大元素。如果元素同時在可視區域的上方和下方渲染,只有可見部分被認為是相關的。目前在Lighthouse中,它是一個隱藏的指標,如果證明是有價值的,後續會推廣。
  • Total Blocking Time[49] (TBT)這是一種新的度量標準,有助於量化頁面在變為可靠交互之前處於非交互狀態的嚴重程度(也就是說,主線程至少在5s內沒有運行超過50ms的任務(長任務))。度量的是從第一次繪畫(FP)到交互時間(TTI)之間的時間長短(在這段時間內,主線程被阻塞足夠長的時間而無法響應用戶輸入)。所以說,低的TBT是良好性能的體現。(感謝
    Boris[50] Artem)
  • Cumulative Layout Shift[51](CLS) 該指標突出顯示了用戶訪問網站時多久遇到一次意外的版式變化(重排)。它研究了不穩定因素及其對整體體驗的影響。分數越低越好。
  • Speed Index[52]度量頁面內容可視化填充的速度,分數越低越好。速度指數分數是根據視覺填充的速度計算的,但它只是一個計算值。它對視口大小也很敏感,所以您需要定義一系列與您的目標用戶是被相匹配的測試配置。請注意,隨著LCP作為一種新度量標準的出現,它變得不那麼重要了(謝謝,Boris, Artem!)。
  • CPU time spent這是顯示主線程被阻塞的頻率和時間的度量指標,受到瀏覽器繪製、渲染、加載和執行JS等動作的影響。高CPU響應時間是不穩定體驗的明顯指標,也就是說,這時候用戶會體驗到他們的操作和響應時間存在明顯的滯後。使用WebPagetest,您可以在“Chrome”選項卡上選擇“Capture Dev Tools Timeline”[53],以顯示在使用WebPagetest的任何設備上運行時,主線程的被阻塞的具體細節。
  • Component-Level CPU Costs[54]類似上面的 CPU time spent,這個由Stoyan Stefanov提出的指標主要用於度量JavaScript對CPU的影響。這個指標的想法是使用每個組件的CPU指令計數來獨立地瞭解每個組件中Javascript其對整體體驗的影響。可以[使用Puppeteer和Chrome來測量]((https://calendar.perfplanet.com/2019/javascript-component-level-cpu-costs/ "使用Puppeteer和Chrome來測量"))。
  • FrustrationIndex[55](沮喪指數)上面介紹的許多指標解釋了特定事件發生的時間,而Tim Vereecket提出的FrustrationIndex指標則著眼於各個里程碑之間的間隔,而不是獨立地衡量它們。它衡量最終用戶感知到的關鍵里程碑,例如 標題可見、第一個內容可見、視覺上準備就緒、頁面準備就緒,並計算一個分數,指示加載頁面時的沮喪程度。間隔時間越大,用戶感到沮喪的可能性就越大。對於用戶體驗而言,這可能是一個很好的KPI。Tim發表了一篇FrustrationIndex介紹及其工作原理的詳細帖子[56]
  • Ad Weight Impact[57]如果您的站點依賴於廣告產生的收入,那麼跟蹤與廣告相關的代碼大小是很有用的。Paddy Ganti寫了1個腳本[58],可以構建了兩個URL(一個正常,一個阻止廣告),通過WebPagetest提示可以生成比較視頻,並報告廣告的增量。
  • Deviation metrics(偏差指標)正如Wikipedia工程師指出的那樣,結果中存在多少差異的數據可以側面反映您測量儀器的可靠性,以及應該對偏差和異常值給予多大的關注。較大的差異表明測試儀器的設置中需要進行調整。它還有助於瞭解某些頁面是否更難以可靠地衡量,例如 “由於第三方腳本會導致重大變化”。跟蹤瀏覽器版本也是一個好主意,這樣可以方便地瞭解新版本的瀏覽器對性能的提高。
  • Custom metrics[59]自定義指標的定義來源於您的業務需求和客戶體驗。它要求您明確頁面中重要的像素、關鍵腳本、必要的CSS和相關資源,並衡量它們對用戶感知速度的影響。對於這一點,您可以監控Hero Rendering Times[60],或者使用Performance API[61],為對您的業務非常重要的事件標記特定的時間戳。 此外,您還可以通過在測試結束時執行任意JavaScript來[使用WebPagetest收集自定義指標](collect custom metrics with WebPagetest "使用WebPagetest收集自定義指標")。

請注意,“首次有效渲染時間(FMP)[62]”並未出現在上面。FMP用於深入瞭解服務器首次輸出任何有意義數據的速度。較大的FMP通常反映JavaScript阻塞了主線程,也可能是後端/服務器出現了其他問題。但是,該度量標準最近已被棄用[63],因為在大約20%的情況下它似乎並不準確。Lighthouse也將在下一版本不再支持FMP[64] 仔細檢查最新的以用戶為中心的性能指標和建議[65],以確保您對頁面性能的監測是可靠的。

Steve Souders對每個指標都進行了詳細的解釋[66]。需要注意的是,可交互時間(TTI)是通過在實驗室環境中運行自動審核來測試的,而首次輸入延遲(FID)這種需要實際的用戶體驗的指標,因此實際用戶在體驗時會明顯感覺比測試中的慢。總體而言,始終測量和跟蹤這兩個參數應該是個不錯的主意。

根據您的應用環境,首選指標可能會有所不同,舉兩個例子:對於Netflix TV UI,輸入響應性,內存使用率和TTI更為關鍵,而對於Wikipedia而言,最先/最後的視覺變化時間點和CPU響應時間指標則更為重要。

:FID和TTI都沒有考慮用戶滾動行為;滾動可以獨立進行,因為它是非主線程的,所以對於許多內容消費站點來說,這些滾動相關指標可能不那麼重要(謝謝Patrick提醒!)

2020前端性能優化清單(一)

network-requests-first-input-delay

以用戶為中心的性能指標可以更好地反映實際的用戶體驗。首次輸入延遲(FID)是一個新的度量標準,它試圖實現這一點。

04 收集典型用戶的設備上的數據

為了收集準確的數據,我們需要徹底全面地選擇要測試的設備。在大多數公司中,這意味著需要調查分析並根據最常見的設備類型來創建用戶畫像。但是一般情況下,僅憑用戶畫像分析並不能提供完整的信息。因為有些用戶可能因為他們的設備體驗太慢或者顯示不完美而離開網站,導致用戶畫像分析時忽略了這部分用戶。因此,另外對目標客戶群體中的通用設備進行研究可能是一個更好的主意。

根據國際數據公司(IDC)的數據顯示,2018年至2019年期間,全球87%的移動電話都是Android設備[67]消費者平均每兩年升級一次手機[68],而在美國,手機更換週期為33個月[69]。全球最暢銷手機的平均售價將低於200美元。

那麼,一個有代表性的慢設備是:已經使用至少24個月的Android設備、價格在200美元或更低、運行在低速3G、400ms RTT和400kbps傳輸模式下,這只是稍微悲觀預期的配置。當然,對於您的公司來說,這可能會非常不同,但這已經足夠接近大多數客戶了。事實上,針對您的目標市場調查一下當前的

亞馬遜暢銷機型[70]可能是個不錯的主意。 (感謝Tim Kadlec,Henri Helvetica和Alex Russel的指點)

那麼選擇什麼樣的測試設備呢?按上面描述的樣子,我們是在開放的設備實驗室裡,選擇Moto G4/G5 Plus,三星中端設備(Galaxy A50,S8),不錯的中檔設備,如Nexus 5X,小米A3或小米Redmi Note 7,以及速度較慢的Alcatel 1X或Cubot X19,這是一個不錯的組合。對於較慢的熱門設備的測試,你也可以買一臺Nexus4,價格只有100美元左右。

此外,檢查每個設備使用的芯片組,機型組合不要過度集中在一個芯片組中: 建議包含幾代的驍龍CPU(Snapdragon)和蘋果CPU(Apple)以及低端的Rockchip、聯發科(Mediatek)(謝謝Patrick提醒)

如果您手頭沒有設備,可以先在在臺式機上模擬移動體驗:節流的3G網絡(例如300ms RTT、1.6 Mbps下行、0.8 Mbps上行)和CPU限速(減速5倍)上進行測試。最終切換到常規3G、低速4G(例如170ms RTT、9 Mbps下行、9 Mbps上行)和Wi-Fi。為了讓性能影響更明顯,你甚至可以參考facebook的做法在每個週二引入2G網絡[71],或者在辦公室設置一個節流的3G/4G網絡[72],更方便地進行測試。

請記住,在移動設備上,我們應該預期會

比臺式機慢4到5倍[73]。移動設備有不同的GPU、CPU、內存和不同的電池。這就是為什麼我們需要真機測試組合,並且始終在這些設備上進行測試[74]

2020前端性能優化清單(一)

tuesday-2g-opt

一週中最慢的一天。Facebook推出了2G的週二服務,讓慢網速更容易被體驗和可視化。

幸運的是,有許多很棒的選項可以幫助您自動收集數據,並根據這些指標衡量您的網站在一段時間內的表現。良好的性能圖表應該含有一組性能指標,並且每個指標都有實驗室數據和真機數據:

  • 綜合測試工具 可以在通過設定好的設備和網絡選項來模擬真機,並收集測試數據(例如Lighthouse,Calibre,WebPageTest)
  • 真實用戶監控(RUM)工具 可以持續評估用戶交互並收集現場數據(例如SpeedCurve、New Relic--並且這些工具也提供綜合測試)

前者在開發期間特別有用,因為它能幫助您在開發產品時識別、拆分和修復性能問題。後者則對於長期維護非常有用,因為它將幫助您瞭解該用戶實際訪問站點時正在發生的性能瓶頸。

通過利用內置的RUM API(如導航時間[75]資源加載時間[76]渲染時間[77]長任務[78]等),綜合測試工具和RUM可一起為您的Web應用程序提供完整的性能圖。您可以使用PWMetrics[79]Calibre[80]SpeedCurve[81]

mPulse[82]Boomerang[83]Sitespeed.io[84],它們都是性能監控的絕佳選擇 此外,使用Server Timing返回頭[85],您甚至可以在頁面中的某個點同時監控後端和前端的性能。

:在瀏覽器外部使用網絡調節器[86]總是比使用瀏覽器內置的更為可靠,例如,DevTools由於其實現方式的原因,在HTTP/2的push過程中,交互時長存在問題(感謝Yoav,Patrick反饋!)。對於Mac OS,我們可以使用Network Link Conditioner[87],Windows中可以使用Windows Traffic Shaper[88],Linux中可以使用netem[89]和FreeBSD的虛擬網絡[90]

2020前端性能優化清單(一)

lighthouse-screenshot

Lighthouse是集成在DevTools中的一個性能審計工具

05 分別建立“乾淨”和“客戶”配置文件用於測試

在監控工具中運行測試時,通常的策略是關閉殺毒軟件和佔用CPU的後臺任務,清除後臺帶寬傳輸,使用乾淨的用戶配置文件進行測試,並且不使用瀏覽器擴展,以避免出現不正確的結果(Firefox[91]Chrome[92])。

此外,最好再研究一下客戶經常使用的擴展,並使用專用的“客戶”配置文件進行測試。實際上,某些擴展可能會對您的應用程序產生明顯的性能影響[93]研究[94]),並且,如果您的用戶經常使用它們,則可能需要先考慮一下。僅僅只用“乾淨”配置文件進行測試可能會導致結果過於樂觀,而在用戶實際體驗的時候表現很糟。

06 與您的同事分享性能文化

確保團隊的每個成員都熟悉性能文化,以免造成誤解。每個決策-無論是設計,營銷還是介於兩者之間的任何決策-都會影響性能。在整個團隊中分配責任和所有權將在以後簡化以性能為中心的決策,根據性能預算和早期定義的優先級來權衡設計決策。

設定現實的目標

07 響應時間100ms,每秒60幀

為了讓交互感覺流暢,頁面響應用戶的輸入動作最好小於100ms。如果超過這個時間,用戶就會覺得這個頁面很遲鈍。Rails是一個以用戶為中心的性能模型,它為您提供了健康頁面的目標:為了達到<100毫秒的響應時間,頁面必須每隔<50毫秒將控制權交還給主線程。輸入延遲估算[95]可以告訴我們是否達到該閾值,理想情況下,它應該低於50ms。對於像動畫這樣的敏感點,最好在你執行動畫的時候什麼都不做。

2020前端性能優化清單(一)

rail-perf-model-opt

RAIL[96], 一個以用戶為中心的性能模型

另外,動畫的每一幀都應在16毫秒內完成,從而達到每秒60幀(1秒÷60 = 16.6毫秒)- 最好在10毫秒以內。由於瀏覽器需要時間才能在屏幕上繪製新的幀,因此您的代碼應在16.6毫秒之前完成執行。有關120fps的目標(例如iPad Pro的屏幕以120Hz運行),Surma提供了一些120fps的渲染性能解決方案[97],但這可能有點超前了,不是我們目前追求的目標。

對性能預期持悲觀態度,[對界面設計持樂觀態度](be optimistic in interface design "對界面設計持樂觀態度"),合理利用瀏覽器空閒時間[98](關注idlize[99]idle-until-urgent[100])。當然,上面說的這些目標適用於衡量運行時性能,而不是加載性能。

08 3G環境下 FID < 100ms, TTI < 5s, Speed Index < 3s, 關鍵文件大小 < 170KB (gzip壓縮後)

雖上述指標可能很難實現,但一個好的最終目標是速度指數(Speed Index)[101]低於3s,

可互動時間(TTI)低於5s[102],對於二次訪問,TTI目標是低於2s(一般需要利用Service Works的離線緩存才能實現)。最大內容繪製時間(LCP)的目標是1s以下,需要最大限度地減少總阻塞時間和累計佈局的變動。可接受的首次輸入延遲(在LightHouse中是最大的潛在首次輸入延遲)要低於130-100ms。如上所述,我們正在考慮的基準是200美元的Android手機(例如Moto G4),在低速3G網絡上,以400ms RTT和400kbps的網絡配置進行模擬測試。

通過網絡中快速展示頁面,有有兩個主要限制因素。一方面,由於TCP慢啟動[103],我們受到網絡傳遞限制: HTML的前14KB(10個TCP數據包,每個1460字節,大約14.25 KB,可以大概這樣估計[104])是最關鍵的有效傳輸塊,並且是內容中唯一可以在第一次網絡往返就傳輸完成的部分( 加上移動網絡喚醒時間的原因,這就是您在RTT為400ms網絡的環境下在1s內能獲得的最多內容)。

:由於TCP通常無法充分利用網絡連接,因此Google開發了TCP瓶頸帶寬和RRT(BBR)[105],這是一種較新的為現代網絡設計的TCP延遲控制和TCP流控制的算法[106]

。在慢網絡能夠根據實際情況阻塞請求,而不是像TCP那樣造成數據包丟失,它明顯更快[107],具有更高的吞吐量和更低的延遲-算法的工作方式也不盡相同[108]。儘早確定靜態資源的優先級仍然很重要,但14 KB可能與BBR無關 (謝謝Victor, Barry!)

另一方面,由於JavaScript解析需要時間,我們在內存和CPU方面存在硬件限制(將在後面詳細討論)。為了實現上面所述的目標,我們必須考慮JavaScript關鍵文件的大小預算。關於該預算應該是多少(這在很大程度上取決於您的項目的性質)有不同的看法,但是壓縮到170KB JavaScript的文件已經需要花費了1s才能在普通手機上進行解析和編譯。假設170KB的文件在解壓縮時擴展到原來的3倍(0.7MB),那在Moto G4 / G5 Plus上這類機型上就已經很大達到“體面的”用戶體驗了。

如果你想瞄準東南亞、非洲或印度等增長中的市場,你必須考慮一組非常不同的限制因素。Addy Osmani介紹了主要的手機限制[109],例如幾乎沒有低成本、高質量的設備、無法獲得高質量的網絡和較貴的流量費用,以及針對環境的PRPL-30性能預算和開發指南。

2020前端性能優化清單(一)

12-30kb-front-end-performance-checklist-2020

根據Addy Osmani所述[110],對於延遲加載的路由中的JS,建議的大小應 <35 KB

2020前端性能優化清單(一)

13-prpl-budget-front-end-performance-checklist-2020

Addy Osmani建議,如果目標是智能手機,就採用PRPL-30性能預算(30KB gzipped+壓縮後的初始化JS包)

事實上,谷歌的Alex Russel建議以130~170KB(gzipped後)作為一個合理的包大小上限。然而在現實世界中,大多數產品甚至都超過很多:現在JS包的中值大小約為417KB,與2015年初相比增長了42%。在中等收入人群的移動設備上,這將帶來15~25秒的可交互時間(TTI)。

2020前端性能優化清單(一)

11-perf-phones-front-end-performance-checklist-2020

2019年全球銷量最高智能手機的Geekbench CPU性能基準。JavaScript是強調單核性能(請記住,與Web平臺的其餘部分相比,它本質上更像是單線程的),並且受CPU的限制。摘自Addy的文章《在20美元的功能手機上快速加載網頁》[111]

當然,JS包大小的最大值限制不是絕對的,我們可以超出上面說的JS包大小預算。我們可以根據瀏覽器主線程的活動(例如:開始渲染之前的繪製時間)設置性能預算,或者跟蹤前端對CPU的佔用量[112]Calibre[113]SpeedCurve[114]Bundlesize[115]等工具可以幫助您控制預算,並且可以集成到您的構建流程中。

最後,性能預算可能不應該是一個固定值。根據網絡連接的不同,性能預算應該有所調整[116]。但是要記住,在慢網速下,無論如何使用,每個包大小都非常“昂貴”(佔用寶貴的帶寬)。

:隨著HTTP/2的廣泛應用、即將到來的5G、快速發展的手機硬件和蓬勃發展的SPA的時代,設定如此僵化的預算聽起來可能有些奇怪。然而,考慮我們面對的網絡和硬件的不可預測性質時,這些性能預算限制聽起來又確實是合理的,包括從擁堵的網絡到緩慢發展的基礎設施,到數據上限、代理瀏覽器、省流量模式和複雜的漫遊費用。

2020前端性能優化清單(一)

file-size-budget-fast-default-addy-osmani-opt

來自Addy Osmani的《默認快速:現代加載最佳實踐》[117](幻燈片19頁)

2020前端性能優化清單(一)

perf-budgets-network-connection

性能預算應根據一般的移動設備的網絡條件進行調整(圖片來源:Katie Hempenius)

定義環境

09 選擇並設置構建工具

不要過於關注那些被認為很酷的工具[118]。堅持在您的開發流程中進行構建優化,無論是Grunt、Gulp、Webpack、Parcel還是這些工具的組合。只要獲得了想要的結果,並且維護構建過程沒有問題,那就足夠了。

在眾多構建工具中,Rollup對開發者的吸引力越來越大,但Webpack似乎是最成熟的一個,它提供了數百個插件來優化構建的大小。儘管剛開始使用Webpack是很困難的。如但果你想掌握它,這裡有一些很棒的資源:

  • Webpack文檔[119] - 顯然這是一個很好的起點,Raja Rao編寫的Webpack代碼混淆[120]和Andrew Welch編寫的[Webpack配置註釋](An Annotated Webpack Config "Webpack配置註釋")都是瞭解webpack一個很好的起點
  • Sean Larkin發佈了1個關於Webpack的免費課程:
    webpack核心概念[121]。Jeffrey Way也發佈了一個關於Webpack的非常棒的免費課程:所有人都必須瞭解的webpack[122]。這兩個對每個想深入研究Webpack的開發者都很友好
  • webpack基礎知識[123]是1個非常全面的4小時課程,由Sean Larkin在FrontendMasters上發佈
  • 如果您對Webpack已經比較熟悉了,那麼可以試試閱讀Rowan Oulton發佈的使用Webpack改善建築性能的現場指南[124],和BenediktRötsch進行的有關將Webpack捆綁壓縮的研究[125]
  • Webpack示例[126]有著數百個現成的Webpack配置,並按照主題和用途分類。另外:還有一個Webpack配置生成器[127],可以生成一個通用的配置文件
  • awesome-webpack[128]是優秀的Webpack資源,庫和工具的集合,有文章,視頻,課程,書籍和示例等,包括在Angular,React中的最佳實踐,當然也包括和框架無關的webpack資源

10 默認使用漸進式增強

儘管這個概念已經提出了這麼多年,將漸進式增強[129]作為基礎原則來指導前端體系結構和部署仍然是一個不錯的選擇。首先設計和構建基礎和核心體驗,然後使用強大的瀏覽器高級特性來增強界面,從而獲得彈性式[130]的用戶體驗。如果你的網站在低性能設備、網速慢、屏幕不好的環境下都能流暢地運行,那麼在速度快的機器上它就會運行更快表現更佳。

實際上,通過自適應服務模塊[131],我們可以同時為低端設備提供“精簡”的核心體驗,而為高端設備提供更復雜的功能。漸進式增強這種模式短期內應該不會消失。

11 選擇一個良好的性能基準

由於有非常多的未知因素影響加載性能-網絡、負載均衡、緩存覆蓋、第三方腳本、解析器阻塞模式、磁盤I/O、IPC延遲、安裝的擴展、防病毒軟件和防火牆、後臺CPU任務、硬件和內存限制、二級/三級緩存的差異、RTTS -- 因此JavaScript的體驗成本非常高[132],僅次於默認情況下阻止頁面呈現的Web字體和經常消耗太多內存的圖像。隨著

性能瓶頸從服務器轉移到客戶端[133],作為開發人員,我們必須更詳細地考慮所有這些未知因素。

上面提到的170KB的預算已經包含關鍵路徑HTML/CSS/JavaScript、路由器、狀態管理、實用程序、框架和應用程序邏輯,所以我們必須徹底檢查我們選擇的框架的網絡傳輸成本、解析/編譯時間和運行時成本[134]。幸運的是在過去的幾年裡,瀏覽器在解析和編譯腳本的速度方面有了巨大的進步[135]。然而,JavaScript的執行仍然是主要的性能瓶頸,因此我們必須密切關注腳本執行時間和網絡傳輸可能會產生的任何影響。

正如Seb Markbège所指出[136]的,衡量框架啟動成本的一個好方法是先渲染視圖,然後刪除視圖再二次渲染,這樣就可以知道框架繪製的成本。因此首次渲染視圖之前往往需要預熱一堆延遲編譯的代碼,更大DOM樹在繪製時受益更多。二次渲染則是模擬頁面上的代碼複用度是如何隨著頁面複雜度的增加而影響性能特徵。

12 評估框架和依賴關係

現在,

不是每個web應用都需要前端框架[137],[在單頁應用程序也不是每個頁面都需要加載框架](not every page of a single-page-application needs to load a framework "在單頁應用程序也不是每個頁面都需要加載框架")。在Netflix的場景中,“從客戶端刪除React,一些第三方庫和相應的應用程序代碼可以將JavaScript的總量減少200KB以上,從而使Netflix首頁登錄的可互動時間減少了50%以上[138]。” 然後,該團隊利用用戶在登錄頁面上花費的時間來預取React,這樣做在用戶可能訪問的後續頁面中就不用繼續加載React了(有關詳細信息,請繼續閱讀[139])。

可能大家都知道,但還是值得一提:確實有一些項目可以從完全刪除現有框架中受益[140]。選擇框架後,您將至少使用幾年,因此,如果需要使用框架,請確保您的選擇是明智的[141],並經過深思熟慮[142]

Inian Parameshwaran評估了最流行的前50個框架的性能[143](用First Contentful Paint[144]評估,即從導航到瀏覽器首次渲染DOM內容的時間)。Inian發現,Vue和Preact是總體來說最快的框架-在臺式機和移動設備上都是如此,其次是React(

幻燈片[145])。可以檢查候選框架和建議的體系結構,並研究其中大多數解決方案的性能,例如使用服務器端渲染或客戶端渲染,或者結合兩者。

基準性能成本很重要。根據Ankur Sethi的研究[146],“在印度,無論你如何優化,React應用程序在普通手機上的加載速度永遠不會比1.1s快,Angular應用程序總是需要2.7s才能完成啟動,Vue應用程序的用戶則需要等待1s才能開始使用它。” 當然,您可能並沒有將印度作為您的主要市場,但是使用次優網絡條件訪問您的web網站的用戶將擁有類似的體驗。使用框架可能會降低用戶體驗,但您的團隊也獲得了可維護性和開發人員效率。因此使用框架需要經過深思熟慮。

您可以在Sacha Greif的12分制評分系統[147]上評估一個框架(或任何JavaScript庫)包括:探索特性、可訪問性、穩定性、性能、包生態系統、社區、學習曲線、文檔、工具、跟蹤記錄、團隊、兼容性、安全性等。考慮到整體耗時較大,在選擇選項之前至少考慮總的大小成本+初始解析時間是個好主意;Preact[148]Inferno[149]

Vue[150]Svelte[151]Polmer[152]等輕量級框架可以很好地完成工作。基線的大小將定義應用程序代碼的約束。

有許多工具可以幫助您就依賴項和可行替代方案的影響做出明智的決策:

  • webpack-bundle-analyzer[153]
  • Source Map Explorer[154]
  • Bundle Buddy[155]
  • Bundlephobia[156]
  • Webpack size-plugin[157]
  • Import Cost for Visual Code[158]

一個好的開端是為您的web應用程序選擇一個好的默認種子工程。Gatsby[159](React),Vuepress[160](Vue),

Preact CLI[161]PWA Starter Kit[162]針對不同框架提供了合理的默認種子,可以在普通移動開發中快速開箱即用。 另外,請查看web.dev特定於針對React和Angular框架的性能指南[163],該指南應該在今年晚些時候進行擴展(感謝Phillip!)。

2020前端性能優化清單(一)

09-high-sell-phones-front-end-performance-checklist-2020

暢銷手機的CPU和計算性能(圖片來源:Addy Osmani)

13 考慮使用PRPL模式和App Shell架構

不同的框架對性能有不同的影響,需要不同的優化策略,因此您必須清楚地瞭解您將依賴的框架的所有細節。在構建Web應用程序時,建議研究PRPL模式[164]App Shell架構[165]。這個理由非常簡單:只推送使頁面初始化並可交互所需要的最小代碼(Push),以便快速呈現初始路由頁面(Render),然後使用Service Worker來緩存和預緩存後續資源(Pre-Caching),再以異步方式延遲加載所需的路由資源(Lazy-Load)。

2020前端性能優化清單(一)

app-build-components-dibweb-c-scalew-879-opt

PRPL代表推送關鍵資源(Pushing critical resource),渲染初始路由(Rendering initial route),預緩存剩餘路由(Pre-caching remaining routes)和按需延遲加載剩餘路由(Lazy-loading remaining routes on demand)

2020前端性能優化清單(一)

appshell-1-o0t8qd-c-scalew-799-opt

App Shell是支持展示用戶界面的最小HTML、CSS和JavaScript

14 是否對API的性能進行了優化?

API是指應用程序通過所謂的socket向內部和第三方應用程序交換數據的通信通道。在

設計和開發API時[166],我們需要一個合理的協議來實現服務器與第三方請求之間的通信。Restful API[167]REST[168])是一種廣泛驗證有效的選擇:它定義了一組約束,開發人員可以遵循這些約束以使內容以高性能,可靠和可伸縮的方式進行訪問。符合REST約束定義的Web服務稱為RESTful Web服務。

與普通的HTTP請求一樣,當從API檢索數據時,服務器響應中的任何延遲都將傳播到最終用戶,從而影響渲染。當資源想要從API檢索某些數據時,它將需要從相應的端點請求數據。渲染來自多個資源的數據的組件,例如在每個評論中包含評論和作者照片的文章,可能需要多次往返到服務器來獲取所有數據,然後才能渲染。此外,通過REST返回的數據量通常超過渲染該組件所需的數據量。

如果許多資源都需要來自某個API的數據,則該API可能會成為性能瓶頸。GraphQL[169]為這些問題提供了高性能的解決方案。本身,GraphQL是API的一種查詢語言,並且是服務器端運行時的,用於通過使用為數據定義的類型系統執行查詢。與REST不同,GraphQL可以在單個請求中檢索所有數據,並且只響應所需的內容,而不會像REST通常那樣過度或不足地獲取數據。

此外,因為GraphQL使用模式(schema,定義數據結構的元數據),所以它可以提前將數據組織成所需的結構,因此使用GraphQL,我們可以刪除用於處理狀態和數據結果的JavaScript代碼[170],從而產生在客戶端上運行更快更乾淨的應用程序代碼。

如果您想開始使用GraphQL,Eric Baer在Smashing Magazine上發表了兩篇精彩的文章:GraphQL入門:為什麼我們需要一種新型API[171]GraphQL入門:API設計的發展[172](感謝Leonardo提醒!)。

2020前端性能優化清單(一)

redux-rest-apollo-graphql

REST和GraphQL之間的區別: 通過左側的Redux+REST的模擬對話和右側的Apollo+GraphQL的模擬對話來說明(圖片來源:Hacker Noon)

15 使用AMP還是Instant Articles?

根據您團隊的優先級和戰略,您可能需要考慮使用Google的AMP[173]或Facebook的Instant Articles[174]或Apple的Apple News[175]。 沒有它們您也可以實現良好的性能,但是AMP確實提供了具有免費內容交付網絡(CDN)的可靠性能框架,而Instant Articles可以提高您在Facebook上的可見性和性能。

這些技術為用戶帶來的明顯好處是:基本可以保證性能,因此有時他們甚至更喜歡AMP/Apple News/Instant Pages的鏈接,而不是“常規”、可能比較臃腫的頁面。對於處理大量第三方內容的內容繁重的網站,這些技術可能會明顯地降低渲染耗時。

這些並不是沒用[176]。例如,根據Tim Kadlec的說法:“AMP文檔往往比它們的同行更快,但這並不一定意味著這個頁面性能更好。從性能的角度來看,AMP並沒有太大的不用”。

對網站所有者來說,好處是顯而易見的:這些格式在他們各自的平臺上都更容易被曝光,並能在搜索引擎中提升排名[177]。您也可以通過AMP作為PWA的數據源,來構建漸進式Web AMP[178]。不利的一面是什麼? 顯然,AMP這類技術類似圍牆的花園,使得開發人員需要開發和維護針對它們的單獨版本,例如Apple的Instant Articles沒有實際的URL[179],我們在代碼中就要單獨處理這種情況(感謝Addy,Jeremy!)。

16 合理選擇CDN

根據您擁有多少動態數據,您可以將內容的某些部分“外包”給靜態站點生成器[180],將其推送到CDN並從中提供靜態版本,從而避免數據庫請求。您甚至可以選擇基於CDN的靜態託管平臺[181],使用交互式組件作為增強功能豐富您的頁面(JAMStack[182])。事實上,其中一些生成器(比如React生態的Gatsby[183])實際上就是個網站編譯器[184],它提供了許多開箱即用的自動化優化。隨著編譯器不斷地為編譯添加優化,編譯後的輸出會越來越小,越來越快。

請注意,CDN也可以提供動態內容。因此,不必將CDN的應用限制在靜態資源。仔細檢查您的CDN是否支持執行壓縮和轉換(例如,在格式方面進行圖像優化,壓縮和調整大小),對servers worker的支持[185],頁面片段緩存,將它們在CDN層面組合頁面的靜態和動態部分(距離用戶最近的服務器)和其他支持的特性。此外,請檢查您的CDN是否也支持HTTP over QUIC(HTTP/3)[186]

注意:根據Patrick Meenan和Andy Davies的研究,設置HTTP/2優先在許多CDN上實際上是無效的[187],因此在選擇CDN時要小心。帕特里克(Patrick)在他最近的HTTP/2優先[188]演講中有更多細節(感謝Barry!)。

未完結,請看下一篇

《 》

《 》

轉發鏈接:https://mp.weixin.qq.com/s/d9J-_aF9K8QTUtemol-EfQ


分享到:


相關文章: