因为 FID
须要一个实在用户的交互,所以无奈用试验数据测试。
为了在试验数据下预测 FID
,通常会用 TBT(Total Blocking Time)
,具体这个指标前面文章会介绍。他们测量的内容不同,但改善 TBT
通常也能改善 FID
。
一个蹩脚的 FID
次要起因是 JS 执行过长,优化 JS 的解析、编译、执行能够间接升高 FID
。
过长的 JS 执行
当 JS 执行过程中,浏览器无奈响应用户交互,因为主线程被占用,为了改善这点,能够:
- 合成长工作
- 优化页面,为交互筹备
- 应用 Web Worker
- 缩小 JS 执行工夫
合成长工作
如果你筹备尝试缩小单个页面的 js 的体积,能够先思考把较长执行的 js 代码分解成小的异步工作。
长工作指的是用户可能会发现页面无响应的期间执行的 js 代码。任何阻塞主线程大于等于 50ms 的代码都是长工作。长工作个别是 js 体积过大的潜在因素(浏览器加载并执行了比页面初始化所须要的更多的 js)。
合成长工作能够升高用户输出提早。
当你采纳最佳实际(例如拆分代码、合成长工作),FID
会有显著改善。尽管 TBT
并非现场数据指标,但这对于改善 FID
和 TTI(Time To Interactive)
都很有帮忙。
优化页面,为交互筹备
造成 FID
和 TBT
分数低有很多起因,大多都是 js 引起的。
本人站点的脚本执行可能会延后交互
- JS 体积过大,执行工夫过长,有效的分包会导致页面响应用户交互变慢,影响
FID
、TBT
、TTI
。逐渐加载代码和功能块能够拆分这些工作,晋升响应速度。 - 服务端渲染看上去页面是进去了,但用户的交互还是受限于 js 的执行工夫,能够思考把更多逻辑代码放在服务端实现,或者在构建的时候创立更多动态内容。
下图是 TBT
得分的优化前后比照。通过将非必须的低廉的脚本的加载和执行移出要害门路,用户就能够更快的去与页面交互。
数据获取会影响交互筹备的很多方面
- 级联的获取数据的水流图(蕴含 js,数据的网络申请等),会导致交互提早。目标是要缩小对级联数据获取的依赖。(缩小申请数)
- 较大的内联数据能够节俭 HTML 的解析工夫,同时影响绘制图像和交互两种指标。目标是要缩小客户端后续解决对数据的依赖。(数据在内联曾经筹备好了,不须要额定申请)
第三方脚本的执行可能会延后交互
- 很多网站都蕴含第三方库的标签和统计代码,这些会导致网络阻塞,使得主线程长时间无奈响应,延后了交互。查找出必须加载的第三方代码。(例如:不滚动到指定地位不展现广告)
- 有时候,第三方的脚本会领先于本站脚本加载,例如加载优先级和带宽限度。尝试着优先加载你感觉能够给用户提供最有价值的货色。
应用 web worker
主线程阻塞是导致输出提早的次要因素之一。web worker 能够让你的代码在后盾过程中执行,把一些非 UI 的操作放在 web worker 中执行能够缩小主线程压力,改善 FID
指标。
能够应用以下的库,让你的站点更不便的集成 web worker:
- Comlink
- Workway
- Workerize
缩小 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/