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

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

當咱們在討論前端性能時咱們在談些什麼?性能的瓶頸又到底在哪兒?是昂貴的 JavaScript 開銷,耗時的網絡字體下載,超大的圖片仍是遲鈍的頁面渲染?搖樹(tree-shaking)、做用域提高(scope hoisting)、代碼分割(code-splitting),以及各類酷炫的加載模式,包括交叉觀察者模式(intersection observer)、服務端推送(server push)、客戶端提示(clients hints)、HTTP/二、service worker 以及 edge worker,研究這些真的有用嗎?還有,最重要的,當咱們着手處理前端性能的時候,咱們該從哪裏開始,該如何去創建一個長期的性能優化體系?前端

早些時候,性能都是所謂的「後顧之憂」。直到項目快結束的時候,它會被歸結爲代碼壓縮(minification)、拼接(concatenation)、靜態資源優化(asset optimization)以及幾行服務器配置的調整。如今回想一下,狀況彷佛已經全然不一樣了。react

性能問題不只僅是技術上的考量,當它被整合進工做流時,在設計的決策中也須要考量性能的因素。性能須要持續地被檢測、監控和優化。同時,網絡在變得愈來愈複雜,這帶來了新的挑戰,簡單的指標追蹤變得再也不可行,由於不一樣的設備、瀏覽器、協議、網絡類型和延遲都會使指標發生明顯變化。(CDN、ISP、緩存、代理、防火牆、負載均衡和服務器,這些都得考慮進去。)linux

所以,若是咱們想囊括關於性能提高的全部要點 — 從一開始到網站最後發佈,那麼最終這個清單應該長啥樣呢?如下是一份(希望是無偏見的、客觀的)2019 前端性能優化年度總結,「介是你沒有看過的船新版本」,它幾乎包括全部你須要考慮的要點,來確保你的網站響應時間夠短、用戶體驗夠流暢、同時不會榨乾用戶的帶寬。android

目錄

起步:計劃與指標

對於持續跟蹤性能,「微優化」(micro-optimization)是個不錯的主意,可是在腦子裏有個明晰的目標也是很必要的 — 量化的目標會影響過程當中採起的全部決策。有許多不一樣的模型能夠參考,如下討論的都基於我我的主觀偏好,請根據我的狀況自行調整。ios

1. 創建性能評估規範

在不少組織裏面,前端開發者都確切地知道哪有最有可能出現問題,以及應該使用何種模式來修正這些問題。然而,因爲性能評估文化的缺失,每一個決定都會成爲部門間的戰場,使組織分裂成孤島。要想得到業務利益相關者的支持,你須要經過具體案例來講明:頁面速度會如何影響業務指標和他們所關心的 KPIgit

沒有開發、設計與業務、市場團隊的通力合做,性能優化是走不遠的。研究用戶抱怨的常見問題,再看看如何經過性能優化來緩解這些問題。github

同時在移動和桌面設備上運行性能基準測試,由公司真實數據獲得定製化的案例研究(case study)。除此之外,你還能夠參考 WPO Stats 上展現的性能優化案例研究及其實驗數據來提高本身對性能優化的敏感性,瞭解爲何性能表現如此重要,它對用戶體驗和業務指標會產生哪些影響。光是明白性能表現很重要還不夠,你還得設立量化的、可追溯的目標,時刻關注它們。web

那麼到底該怎麼作呢?在 Allison McKnight 名爲 Building Performance for the Long Term 的演講中,她詳細地分享了本身如何在 Etsy 創建性能評估文化的案例chrome

Brad Frost and Jonathan Fielding’s Performance Budget Calculator

Brad Frost 的 Performance budget builder 和 Jonathan Fielding 的 Performance Budget Calculator 能夠幫助你創建性能預算並將其可視化表示出來。(預覽

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

根據一項心理學研究,若是你但願你的用戶感受到大家的網站用起來比競爭對手快,那麼你須要比他們快至少 20%。研究你的主要對手,收集他們的網站在移動和桌面設備上的性能指標,肯定超越他們的最低要求。爲了獲得準確的結果和目標,首先去研究大家產品的用戶行爲,以後模仿 90% 用戶的行爲來進行測試。

爲了更好地瞭解你的對手的性能表現,你可使用 Chrome UX ReportCrUX,一組現成的 RUM 數據集,Ilya Grigorik 的視頻介紹),Speed Scorecard(可同時估算性能優化將如何影響收入),真實用戶體驗測試比較(Real User Experience Test Comparison)或者 SiteSpeed CI(基於集成測試)。

注意:若是你使用 Page Speed Insights(是的,它還沒被拋棄),你能夠獲得指定頁面詳細的 CrUX 性能數據,而不是隻有一些粗略的綜合數據。在爲具體頁面(如「首頁」、「產品列表頁面」)設立性能目標時,這些數據會很是有用。另外,若是你正在使用 CI 來監測性能預算,當使用 CrUX 來確立目標時,你須要確保測試環境與 CrUX 一致。(感謝 Patrick Meenan!)

收集數據,創建一個表格,削減掉 20%,以此創建你的目標性能預算。那麼如今你有了量化的對照組樣本。事情正逐步走向正軌,只要你時刻把這份預算記在內心,而且每次都交付儘量少的代碼以縮短可交互時間。

須要些資料來上手?

一旦確立好合適的性能預算,你就能夠藉助 Webpack Performance Hints and BundlesizeLightouse CI, PWMetricsSitespeed CI 把它們整合進打包流程中,在請求合併時強制檢測性能預算,並在 PR 備註中註明得分記錄。若是你須要個性化定製,你可使用 webpagetest-charts-api,它提供了一系列能夠從 WebPagetest 的結果生成圖表的 API。

舉個例子,正如 Pinterest 同樣,你能夠建立一個自定義的 eslint 規則,禁止導入重依賴(dependency-heavy)的文件和目錄,從而避免打包文件變得臃腫。設定一個團隊內共享的「安全」依賴包列表。

除了性能預算外,仔細考慮那些對大家業務價值最大的關鍵用戶操做。規定並討論可接受的關鍵操做響應時間閾值,並就「UX 就緒」耗時評分在團隊內達成共識。大多數狀況下,用戶的操做流程會涉及到許多不一樣公司部門的工做,所以,就「時間閾值」達成共識能夠爲從此關於性能的溝通提供支持,避免沒必要要的討論。確保對新增資源和功能帶來的資源開銷了如指掌。

另外,正如 Patrick Meenan 提議的,在設計過程當中,規劃好加載的順序和取捨是絕對值得的。若是你預先規劃好哪部分更重要,並肯定每部分出現的順序,那麼同時你也會知道哪些部分能夠延遲加載。理想狀況下,這個順序也會反映出 CSS 和 JavaScript 文件的導入順序,所以在打包階段處理它們會變得更容易些。除此之外,還得考慮頁面加載時中間態的視覺效果(比方說,當網絡字體尚未加載徹底時)。

規劃,規劃,規劃。儘管在早期就投入那些能起到立竿見影效果的優化彷佛至關有吸引力 — 這對須要快速決勝的項目而言多是個不錯的策略,可是若是沒有務實的規劃和因地制宜的性能指標,很難保證性能優先能一直受到重視。

首次繪製(First Paint)、首次有內容繪製(First Contentful Paint)、首次有意義繪製(First Meaningful Paint)、視覺完備(Visual Complete)、首次可交互時間(Time To Interactive)的區別。完整文檔。版權:@denar90

3. 選擇合適的指標

並非全部的指標都同等重要。研究哪一個指標對你的應用最重要,一般來講它應該與開始渲染你的產品中最重要的那些像素的速度以及提供輸入響應所需的時間相關。這個要點將爲你指明最佳的優化目標,提供努力的方向。

無論怎樣,不要老是盯着頁面完整載入的時間(比方說 onloadDOMContentLoaded),要站在用戶的角度去看待頁面加載。也就是說,須要關注一組稍微不一樣的指標。事實上,「選擇正確的指標」是沒有絕對完美方案的。

根據 Tim Kadlec 的研究和 Marcos Iglesias 在他的演講中提到的,傳統的指標能夠歸爲幾種類型。一般,咱們須要全部的指標來構建完整的性能畫像,可是在特定場景中,某些指標可能比其餘的更重要些。

  • 基於數量的指標衡量請求數量、權重和性能評分等。對於告警和監控長期變化頗有用,但對理解用戶體驗幫助不大。

  • 里程碑式指標使用加載過程當中的各個狀態來標記,好比:首位字節時間(Time To First Byte)首次可交互時間(Time To Interactive)。對於描述用戶體驗和指標頗有用,但對了解加載過程當中的狀況幫助不大。

  • 渲染指標能夠估計內容渲染的時間,例如渲染開始時間(Start Render)速度指數(Speed Index)。對於檢測和調整渲染性能頗有用,但對檢測重要內容什麼時候出現、什麼時候可交互幫助不大。

  • 自定義指標衡量某個特定的、個性化的用戶事件,好比 Twitter 的首次發推時間(Time To First Tweet),Pinterest 的 收藏等待時間(PinnerWaitTime)。對準確描述用戶體驗頗有用,但不方便規模化以及與競品比較。

爲了使性能畫像更加完整,咱們一般會在全部類型中都選擇一些有用的指標。通常來講,最重要的是如下幾個:

  • 首次有效繪製(First Meaningful Paint,FMP)

    反映主要內容出如今頁面上所需的時間,也側面反映了服務器輸出任意數據的速度。FMP 時間過長通常意味着 JavaScript 阻塞了主線程,也有多是後端/服務器的問題。

  • 首次可交互時間(Time to Interactive,TTI)

    在此時間點,頁面佈局已經穩定,主要的網絡字體已經可見,主線程已能夠響應用戶輸入 — 基本上意味着只是用戶能夠與 UI 進行交互。是描述「網站可正常使用前,用戶所須要等待的時長」的關鍵因素。

  • 首次輸入延遲(First Input Delay,FID 或 Input responsiveness)

    從用戶首次與頁面交互,到網站可以響應該交互的時間。與 TTI 相輔相成,補全了畫像中缺乏的一塊:在用戶切實與網站交互後發生了什麼。標準的 RUM 指標。有一個 JavaScript 庫 能夠在瀏覽器中測量 FID 耗時。

  • 速度指數(Speed Index)

    衡量視覺上頁面被內容充滿的速度,數值越低越好。速度指數由視覺上的加載速度計算而得,只是一個計算值。同時對視口尺寸也很敏感,所以你須要根據目標用戶設定測試配置的範圍。(感謝 Boris!)

  • CPU 耗時

    描述主線程處理有效負載時繁忙程度的指標,顯示在繪製、渲染、運行腳本和加載時,主線程被阻塞的頻次和時長。高的 CPU 耗時明顯地意味着卡頓的用戶體驗。利用 WebPageTest,你能夠在 「Chrome」 標籤頁上選擇 「Capture Dev Tools Timeline」 選項來暴露出可能的主線程崩潰(得益於 WebPageTest 能夠在任何設備上運行)。

  • 廣告的影響(Ad Weight Impact)

    若是你的站點的利潤主要來源於廣告,那麼追蹤廣告相關代碼的體積就頗有用了。Paddy Ganti 的腳本能夠構築兩條 URL(一條有廣告,一條沒有),而且利用 WebPageTest 生成一個比較視頻,並顯示區別。

  • 偏離度指標(Deviation metrics)

    正如 Wikipedia 的工程師所指出的,你的結果中數據的變化在必定程度上能夠反映出設施的可靠性,以及你該花多少精力來關注這些偏離度和極端值。過大的變化意味着你極可能須要對目前設施的配置作一些調整,它也能幫助咱們瞭解有某些頁面是難以可靠地用指標衡量的,例如由於第三方腳本而致使的明顯變化。另外,追蹤瀏覽器版本也是個不錯的主意,它可能幫助你獲悉新版瀏覽器能夠帶來的性能變化。

  • 自定義指標(Custom metrics)

    自定義指標可由具體業務和用戶體驗的須要專門設置。它須要你對重要像素、關鍵腳本、必要 CSS 樣式和相關靜態資源有個清晰的概念,並可以測算用戶須要多長時間來下載它們。關於這點,你可使用 Hero Rendering TimesPerformance API,爲重要業務事件建立時間戳。另外,你也能夠經過在 WebPageTest 測試完成後運行自定義的腳原本收集自定義的指標

Steve Souders 寫了一篇文章詳細地介紹了各個指標。須要注意的是:首次交互時間是在實驗環境下經過自動化審查獲得的,而首次輸入延遲則表示真實用戶在使用中感覺到的實際延遲。總而言之,始終觀測和追蹤這兩個指標會是個好主意。

不一樣的應用,偏好的指標可能會不一樣。舉個例子,對於 Netflix TV 的 UI 界面而言,關鍵輸入響應、內存使用和首次可交互時間會更重要些,而對於 Wikipedia,首末視覺變化和 CPU 耗時指標會顯得更重要些。

注意:FID 和 TTI 都不關心滾動表現。滾動事件能夠獨立發生,由於它是主線程外的。所以,對於許多內容爲主的站點而言,這些指標可能並非很重要。(感謝 Patrick!)。

以用戶爲中心的性能指標能夠幫助更好地瞭解真實用戶體驗。首次輸入延遲(FID)是一個嘗試去實現這一目標的新指標。(戳此瞭解詳情

4. 在目標用戶的典型設備上收集數據

爲了獲得準確的數據,咱們須要選擇合適的測試設備。Moto G4 會是一個不錯的選擇,或者是 Samsung 的一款中端產品,又或者是一款如 Nexus 5X 同樣中庸的設備,以及 Alcatel 1X 這樣的低端設備。你能夠在 open device lab 找到這些。若是想在更慢的設備上測試,你能夠花差很少 $100 買一臺 Nexus 2。

若是你手上沒有合適的設備,你能夠經過網絡限速(好比:150ms RTT,下行 1.5Mbps,上行 0.7Mbps)以及 CPU 限速(慢 5 倍)在電腦上模擬移動端體驗。而後,再切換到普通 3G、4G 和 WIFI 網絡進行測試。爲了使性能影響更加明顯,你甚至能夠引入 2G 星期二,或者爲了更方便測試,在辦公室限制 3G 網絡

時刻記着:在移動設備上,運行速度應該會比在桌面設備上慢 4-5 倍。移動設備具備不一樣的 GPU、CPU、內存、電池特性。若是說慢速網絡制約了下載時間的話,那麼手機較爲慢速的 CPU 則制約瞭解析時間。事實上,移動設備上的解析時間一般要比桌面設備長 36%。所以,必定要在一部平均水準的設備上進行測試 — 一部你的用戶中最具表明性的設備。

Introducing the slowest day of the week

在一週中選擇一天讓網速變慢。Facebook 就有 2G 星期二來提升對低速網絡的關注。(圖片來源

幸運的是,有不少工具能夠幫你自動化完成數據收集、評估上述性能指標隨時間變化趨勢。記住,一個好的性能畫像應該包括一套完整的性能指標、實驗數據和實際數據

  • 集成測試工具能夠在預先規定了設備和網絡配置的可複製環境中收集實驗數據。例如:LighthouseWebPageTest
  • 真實用戶監測(RUM) 工具能夠持續評估用戶交互,收集實際數據。例如,SpeedCurveNew Relic,二者也都提供集成測試工具。

前者在開發階段會很是有用,它能夠幫助你在開發過程當中發現、隔離、修復性能問題。後者在維護階段會頗有用,它能夠幫助你瞭解性能瓶頸在哪兒,由於這都是真實用戶產生的數據。

經過深刻了解瀏覽器內置的 RUM API,如 Navigation TimingResource TimingPaint TimingLong Tasks 等,集成測試和 RUM 二者搭配構建出完整的性能畫像。你可使用 PWMetricsCalibre, SpeedCurvemPulseBoomerangSitespeed.io 來進行性能監測,它們都是不錯的選擇。另外,利用 Server Timing header,你甚至能夠同時監測後端和前端性能。

注意: 建議使用瀏覽器外部的網絡節流器,由於瀏覽器的 DevTools 可能會存在一些問題,好比:因爲實現方法的緣由,HTTP/2 push 可能會有問題。(感謝 Yoav 和 Patrick!)對於 Mac OS,咱們能夠用 Network Link Conditioner;對於 Windows,能夠用 Windows Traffic Shaper;對於 Linux,能夠用 netem;對於 FreeBSD,能夠用dummynet

Lighthouse

Lighthouse — DevTools 自帶的性能審查工具。

5. 爲測試設立「純淨」、「接近真實用戶」的瀏覽器配置(Profile)

使用被動監控工具進行測試時,一個常見的作法是:關閉反病毒軟件和 CPU 後臺任務,關閉後臺網絡鏈接,使用沒有安裝任何插件的「乾淨的」瀏覽器配置,以免結果失真。(FirefoxChrome)。

然而,瞭解你的用戶一般會使用哪些插件也是個不錯的主意,而後使用精心設計的「接近真實用戶的」瀏覽器配置進行測試。事實上,某些插件可能會給你的應用帶來顯著的性能影響。若是你有不少用戶在使用這些插件,你可能須要考慮這些影響。「乾淨的」用戶瀏覽器配置可能有些過於理想化了,可能會與實際狀況截然不同。

6. 與團隊其餘成員分享這份清單

確保你的每一位同事都充分熟悉這份清單,從而避免在之後出現誤解。每個決策都會帶來性能影響,整個項目會從前端開發者正確地對待性能問題而獲益良多,從而使得團隊中的每個人都負起責任來,而不只僅只是前端。根據性能預算和清單中定義的優先級來制定設計決策。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


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

相關文章
相關標籤/搜索