因为 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。