交互響應性能之優化FID

因爲 FID 須要一個真實用戶的交互,因此沒法用實驗數據測試。html

爲了在實驗數據下預測 FID,一般會用 TBT(Total Blocking Time),具體這個指標後面文章會介紹。他們測量的內容不一樣,但改善 TBT 一般也能改善 FIDvue

一個糟糕的 FID 主要緣由是JS執行過長,優化JS的解析、編譯、執行能夠直接下降 FIDreact

過長的JS執行

當JS執行過程當中,瀏覽器沒法響應用戶交互,由於主線程被佔用,爲了改善這點,能夠:webpack

  • 分解長任務
  • 優化頁面,爲交互準備
  • 使用 Web Worker
  • 減小JS執行時間

分解長任務

若是你準備嘗試減小單個頁面的js的體積,能夠先考慮把較長執行的js代碼分解成小的異步任務。git

長任務指的是用戶可能會發現頁面無響應的時期執行的js代碼。任何阻塞主線程大於等於50ms的代碼都是長任務。長任務通常是js體積過大的潛在因素(瀏覽器加載並執行了比頁面初始化所須要的更多的js)。github

分解長任務能夠下降用戶輸入延遲。web

當你採用最佳實踐(例如拆分代碼、分解長任務),FID 會有顯著改善。雖然 TBT 並不是現場數據指標,但這對於改善 FIDTTI(Time To Interactive) 都頗有幫助。瀏覽器

優化頁面,爲交互準備

形成 FIDTBT 分數低有不少緣由,大多都是js引發的。babel

本身站點的腳本執行可能會延後交互

  • JS體積過大,執行時間過長,無效的分包會致使頁面響應用戶交互變慢,影響 FIDTBTTTI。逐步加載代碼和功能塊能夠拆分這些任務,提高響應速度。
  • 服務端渲染看上去頁面是出來了,但用戶的交互仍是受限於js的執行時間,能夠考慮把更多邏輯代碼放在服務端實現,或者在構建的時候建立更多靜態內容。

下圖是 TBT 得分的優化先後對比。經過將非必須的昂貴的腳本的加載和執行移出關鍵路徑,用戶就能夠更快的去與頁面交互。網絡

數據獲取會影響交互準備的不少方面

  • 級聯的獲取數據的水流圖(包含js,數據的網絡請求等),會致使交互延遲。目的是要減小對級聯數據獲取的依賴。(減小請求數)
  • 較大的內聯數據能夠節省HTML的解析時間,同時影響繪製圖像和交互兩種指標。目的是要減小客戶端後續處理對數據的依賴。(數據在內聯已經準備好了,不須要額外請求)

第三方腳本的執行可能會延後交互

  • 不少網站都包含第三方庫的標籤和統計代碼,這些會致使網絡阻塞,使得主線程長時間沒法響應,延後了交互。查找出必須加載的第三方代碼。(例如:不滾動到指定位置不展現廣告)
  • 有時候,第三方的腳本會搶先於本站腳本加載,例如加載優先級和帶寬限制。嘗試着優先加載你以爲能夠給用戶提供最有價值的東西。

使用 web worker

主線程阻塞是致使輸入延遲的主要因素之一。web worker可讓你的代碼在後臺進程中執行,把一些非UI的操做放在web worker中執行能夠減小主線程壓力,改善 FID 指標。

可使用如下的庫,讓你的站點更方便的集成web worker:

減小JS執行時間

  • 延後加載未使用的js
  • 最小化無用的polyfill

延後加載未使用的js

經過開發者工具中的coverage的tab頁能夠查看各資源的有效使用率。

爲了減小無用JS,能夠:

  • 把你的代碼拆分紅多個chunk,按需加載
  • 使用 async 或者 defer 延後加載非關鍵腳本,包含第三方腳本

代碼拆分指的是將一個大的單個JS拆分紅多個小的,根據條件去加載對應的JS。現代瀏覽器已經支持按需加載:

import('module.js')    
  .then((module) => {    
    // Do something with the module.    
  });

除了經常使用瀏覽器支持之外,一些構建系統也支持:

  • webpack,rollup,parcel等構建工具
  • angular,react,vue等客戶端框架

除了可使用代碼拆分,也可使用 async 或者 defer 來延後加載非關鍵腳本。

<script defer src="…"></script>    
<script async src="…"></script>

除非有特殊緣由,通常第三方腳本均可以默認採用這種方式加載。

最小化無用的polyfill

若是你用了一些js高級語法,你可能須要將這些代碼轉換成舊版瀏覽器支持的語法,或者引入polyfill來支持。

最好的作法是,若是瀏覽器支持這些語法,不引入polyfill。最小化無用的polyfill,而且將它們的使用限制在須要它們的環境中,能夠下降js的體積。

優化polyfill的使用,能夠:

  • 若是你是用babel轉義,使用 @babel/preset-env 能夠只包含你須要支持的瀏覽器的polyfill。對於babel 7.9,能夠開啓 bugfixes 配置,進一步減小無用的polyfill。
  • 使用 module/nomodule 的模式傳輸兩份不一樣的bundle。(@babel/preset-env 也支持,能夠經過 target.esmodules
<script type="module" src="modern.js"></script>    
<script nomodule src="legacy.js" defer></script>

這樣能夠保證支持js模塊的瀏覽器,能夠加載模塊化的打包文件,不支持的瀏覽器能夠加載轉義後的打包文件。

開發者工具

Lighthouse 6.0 不能測試 FID,由於它是一個現場數據指標,可是 TBT 能夠做爲替代品測試。針對 TBT 的優化項對 FID 也一樣有效。

總結

實際項目的優化須要頻繁的使用開發者工具 performance 和 lighthouse。針對長任務進行拆解,針對未使用的js進行移除,針對複雜的js使用web worker。最後再針對舊版瀏覽器和新版瀏覽器加載不一樣資源,以保證新版瀏覽器的對polyfill更少的依賴。若是使用webpack打包的項目,能夠查看打包的分佈圖,針對性的去優化每個bundle。

參考

https://web.dev/optimize-fid/

相關文章
相關標籤/搜索