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

Hopsken發表於2019-01-23

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

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

早些時候,效能都是所謂的“後顧之憂”。直到專案快結束的時候,它會被歸結為程式碼壓縮(minification)、拼接(concatenation)、靜態資源優化(asset optimization)以及幾行伺服器配置的調整。現在回想一下,情況似乎已經全然不同了。

效能問題不僅僅是技術上的考量,當它被整合進工作流時,在設計的決策中也需要考量效能的因素。效能需要持續地被檢測、監控和優化。同時,網路在變得越來越複雜,這帶來了新的挑戰,簡單的指標追蹤變得不再可行,因為不同的裝置、瀏覽器、協議、網路型別和延遲都會使指標發生明顯變化。(CDN、ISP、快取、代理、防火牆、負載均衡和伺服器,這些都得考慮進去。)

因此,如果我們想囊括關於效能提升的所有要點 — 從一開始到網站最後釋出,那麼最終這個清單應該長啥樣呢?以下是一份(但願是無偏見的、客觀的)2019 前端效能優化年度總結,“介是你沒有看過的船新版本”,它幾乎包括所有你需要考慮的要點,來確保你的網站響應時間夠短、使用者體驗夠流暢、同時不會榨乾使用者的頻寬。

目錄

起步:計劃與指標

對於持續跟蹤效能,“微優化”(micro-optimization)是個不錯的主意,但是在腦子裡有個明晰的目標也是很必要的 — 量化的目標會影響過程中採取的所有決策。有許多不同的模型可以參考,以下討論的都基於我個人主觀偏好,請根據個人情況自行調整。

1. 建立效能評估規範

在很多組織裡面,前端開發者都確切地知道哪有最有可能出現問題,以及應該使用何種模式來修正這些問題。然而,由於效能評估文化的缺失,每個決定都會成為部門間的戰場,使組織分裂成孤島。要想獲得業務利益相關者的支援,你需要通過具體案例來說明:頁面速度會如何影響業務指標和他們所關心的 KPI

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

同時在移動和桌面裝置上執行效能基準測試,由公司真實資料得到定製化的案例研究(case study)。除此以外,你還可以參考 WPO Stats 上展示的效能優化案例研究及其實驗資料來提升自己對效能優化的敏感性,瞭解為什麼效能表現如此重要,它對使用者體驗和業務指標會產生哪些影響。光是明白效能表現很重要還不夠,你還得設立量化的、可追溯的目標,時刻關注它們。

那麼到底該怎麼做呢?在 Allison McKnight 名為 Building Performance for the Long Term 的演講中,她詳細地分享了自己如何在 Etsy 建立效能評估文化的案例

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!)。

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

以使用者為中心的效能指標可以幫助更好地瞭解真實使用者體驗。首次輸入延遲(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前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章