因爲 FID
須要一個真實用戶的交互,因此沒法用實驗數據測試。html
爲了在實驗數據下預測 FID
,一般會用 TBT(Total Blocking Time)
,具體這個指標後面文章會介紹。他們測量的內容不一樣,但改善 TBT
一般也能改善 FID
。vue
一個糟糕的 FID
主要緣由是JS執行過長,優化JS的解析、編譯、執行能夠直接下降 FID
。react
當JS執行過程當中,瀏覽器沒法響應用戶交互,由於主線程被佔用,爲了改善這點,能夠:webpack
若是你準備嘗試減小單個頁面的js的體積,能夠先考慮把較長執行的js代碼分解成小的異步任務。git
長任務指的是用戶可能會發現頁面無響應的時期執行的js代碼。任何阻塞主線程大於等於50ms的代碼都是長任務。長任務通常是js體積過大的潛在因素(瀏覽器加載並執行了比頁面初始化所須要的更多的js)。github
分解長任務能夠下降用戶輸入延遲。web
當你採用最佳實踐(例如拆分代碼、分解長任務),FID
會有顯著改善。雖然 TBT
並不是現場數據指標,但這對於改善 FID
和 TTI(Time To Interactive)
都頗有幫助。瀏覽器
形成 FID
和 TBT
分數低有不少緣由,大多都是js引發的。babel
FID
、TBT
、TTI
。逐步加載代碼和功能塊能夠拆分這些任務,提高響應速度。下圖是 TBT
得分的優化先後對比。經過將非必須的昂貴的腳本的加載和執行移出關鍵路徑,用戶就能夠更快的去與頁面交互。網絡
主線程阻塞是致使輸入延遲的主要因素之一。web worker可讓你的代碼在後臺進程中執行,把一些非UI的操做放在web worker中執行能夠減小主線程壓力,改善 FID
指標。
可使用如下的庫,讓你的站點更方便的集成web worker:
經過開發者工具中的coverage的tab頁能夠查看各資源的有效使用率。
爲了減小無用JS,能夠:
async
或者 defer
延後加載非關鍵腳本,包含第三方腳本代碼拆分指的是將一個大的單個JS拆分紅多個小的,根據條件去加載對應的JS。現代瀏覽器已經支持按需加載:
import('module.js') .then((module) => { // Do something with the module. });
除了經常使用瀏覽器支持之外,一些構建系統也支持:
除了可使用代碼拆分,也可使用 async
或者 defer
來延後加載非關鍵腳本。
<script defer src="…"></script> <script async src="…"></script>
除非有特殊緣由,通常第三方腳本均可以默認採用這種方式加載。
若是你用了一些js高級語法,你可能須要將這些代碼轉換成舊版瀏覽器支持的語法,或者引入polyfill來支持。
最好的作法是,若是瀏覽器支持這些語法,不引入polyfill。最小化無用的polyfill,而且將它們的使用限制在須要它們的環境中,能夠下降js的體積。
優化polyfill的使用,能夠:
@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。