🌞Moon Will Know
🏐

前端性能监控指标和首屏优化

我们在进行前端项目的优化时,经常会需要优化页面的加载性能,在 window 中有着 DOMContentLoadedload 事件,分别代表 DOM 构造完成和首屏资源加载完成。但是在我们使用 UI 框架来构造 WEB 应用时,都是通过 JS 来操作 DOM 完成页面的构建,DOMContentLoadedload 事件并不能准确地衡量应用的首屏时间。
我们打开 Chrome 的控制台时可以看到性能一栏,使用这个功能检测页面的加载过程,可以发现几个阶段,依次是:FP,FCP,DCL,L

性能指标事件

  • FP (First Paint):渲染出第一个像素点,一般在 HTML 全部解析或解析一部分时触发。
  • FCP (First Contentful Paint):渲染出第一个内容,可以是文本,图片或 canvas。
  • DCL(DOMContentLoaded):DOM 解析完成,style 和 图片 等可能还处于加载状态,对应 DOMContentLoaded 事件,document.onloaddocument.body.onload
  • LCP(largest contentful Paint):页面可视区域内可见的最大的片或文本快完成渲染的时间。
  • L(load):页面中所有资源都被加载完成(包括异步加载,但不包括延时加载的资源,如图片的 lazy),即 window.onload() 事件。

加载相对事件

  • 白屏事件:从输入网址到浏览器出现第一个元素,即 FP 事件。
  • 首屏事件:从输入地址到浏览器第一屏渲染完成,即 FCP 事件。
FCP 事件代表第一个内容被渲染出来,如果需要更关键的内容标志首屏,可以采用 LCP 事件。

交互事件

  • FID(First Input Delay):用户第一次与网站交互(如单击链接或按钮,或操作一些自定义控件)时到浏览器对交互做出响应经过的时间。
  • TTI(Time to interactive):页面开始加载到完成渲染,并且所有可见元素的关联事件的响应函数都注册完成,事件响应函数可以在触发后 50ms 内执行(无 longtask 阻塞)。
    • longTask:阻塞线程超过 50ms 或以上的任务

监听页面加载事件

可以通过 PerformanceTiming API
通过 web-vitals 获取
 
关于埋点接口的几个问题: 1. 为什么会采用 1x1 的透明 gif 来传递指标 因为埋点服务器一般为第三方,存在跨域问题。而 1x1 的透明 gif 在支持跨域的格式中最小。 2. 埋点采用的请求方式 navigator.sendBeacon()这个方法可用于通过 HTTP 将少量数据异步传输到 Web 服务器 而不占用进程 3. 埋点还可以放在 worker 线程中

React 优化首屏事件

对于 React 应用来说,FP 和 FCP 事件都在 DCL 事件之后。所以我们的目标是让 mian.js 尽快执行。我们可以从文件结构和文件大小两方面来优化:

文件结构

这部分是 Webpack 打包时就自动做好的,在 HTML 中引入的 mian chunk 被自动加上了 defer。
  • 减少 DOM 树的内容和层级,减少 DOM 的解析和渲染时间。
  • 将 CSS 放在页面开始位置,来让 CSSOM 尽快加载和解析。
  • 将 JS 放在页面底部位置,使用 async 或 defer 避免 JS 阻塞 DOM。

文件大小

  • 打包时对 JS 文件进行 uglify。
  • 项目内的组件和路由页面采用动态引入,减少 main chunk 的大小。
  • 打包生成 .gz 文件,nginx 开启 gzip
  • 使用 webpack-bundle-analyzer 对项目进行依赖分析,对较大的包采用动态引入或者 CDN 引入。对于 lodash 可以采用引入子包的方法。
  • 开启 tree shaking 移除无用代码。

采用 Next.js

使用 Next 无论是 静态加载还是服务端渲染,都会预先返回 DOM 结构,不用等待全部的逻辑代码,所以 Next.js 的首屏事件在 DCL 事件之前。