为了从一个切图仔变成一个前端工程师,性能优化是必不可少的,有时便会说,这个页面性能提高了xx%,速度变快了xx秒,那么问题来了,如何才能正确观测到性能的变化呢,这里记录一些思路
浏览器相关
-
开发者工具→性能:
-
可以直接看到LCP(最大内容绘制),CLS(积累布局偏移),INP(下一次绘制时间)
-
通过左上角的“录制”,并在录制中操作页面,可以看到这段时间的性能信息
-
操作方式:通过滚轮进行缩放/左右移动,按住shift+滚轮或者按住鼠标拖动可以上下滚动,shift+鼠标可以选中其中的一段时间查看摘要
-
“主要”:可以看到这段时间的火焰图
- 蓝色:加载(Loading)事件
- 黄色:脚本运算(Scripting)事件
- 紫色:渲染(Rendering)事件
- 绿色:绘制(Painting)事件
- 灰色:其他(Other)
- 闲置:浏览器空闲
-
-
点击“录制”旁边的“禁止”按钮退出
-
在后续步骤→环境设置中可以模拟低配CPU和慢速网络(设置慢速网络也会影响网络面板的设置,记得改回来)
-
-
开发者工具→Lignthouse
- 注意:Lighthouse 等工具在模拟环境中加载页面(导航或快照模式),但没有用户,因此无法衡量 INP,因为没有用户输入
- 默认的导航模式会被indexDB影响,无法正确测出性能数据,可以选择时间跨度或者快照模式
- 通过Lignthouse的分析可以生成网页诊断报告,精确判断优化的要点,避免过度优化
- 时间跨度的诊断报告中点击“查看跟踪记录”会跳转到“性能”面板中
-
performance API
-
使用
performance.now()
获取当前时间再相减 -
配合使用
performance.mark()
与performance.measure()
//创建起始标记 performance.mark('start'); //耗时操作 //... // 创建结束标记 performance.mark('end'); //测量两个标记之间的时间差,并命名为'my-measure' performance.measure('my-measure', 'start', 'end'); //获取测量结果 const measures = performance.getEntriesByName('my-measure'); console.log('执行耗时:', measures[0].duration.toFixed(2), '毫秒'); /* 这个measures具有以下属性: name : 创建标记时通过参数指定的标记名 entryType : entry的类型,此处为 mark startTime : 创建 mark 时的时间戳 duration : 该事件的耗时,此处为0,mark 没有持续时间 */
-
-
使用google提供的
web-vitals
库直接打印性能信息:(要鼠标点击一下才有输出)<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Web Vitals Test</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <p> <img style="max-width: 360px" src="<https://placekitten.com/g/3840/2160>" alt="Kitten" /> </p> <p>Text below image</p> <script type="module"> import { getCLS, getFID, getLCP, } from "<https://cdn.skypack.dev/web-vitals@3.0.0>"; getCLS(console.log); getFID(console.log); getLCP(console.log); </script> </body> </html>
来源:developers.google.com/codelabs/ch…
也可以将信息发送到Google Analytics进行分析(然后可以在 Google Analytics的“热门事件”报告中查看该网页的核心网页指标)
-
可以使用web-vitals-extension插件进行性能检测,但是该插件的所有功能已经集成到开发者工具的性能面板中了
react相关
-
使用React Profiler API
- 用
<Profiler>
包裹住要测量性能的元素,在onRender
的回调中拿到性能信息
const handleReorder = ( id, phase, actualDuration, baseDuration, startTime, commitTime ) => { console.log("id:", id); console.log("phase:", phase); //为 "mount"、"update" 或 "nested-update" 中之一。这可以让开发者知道组件树是首次挂载还是由于 props、state 或 hook 的更改而重新渲染 console.log("actualDuration:", actualDuration); //在此次更新中,渲染 <Profiler> 组件树的毫秒数(使用useMemo之后变化明显) console.log("baseDuration:", baseDuration); //估算在没有任何优化的情况下重新渲染整棵 <Profiler> 子树所需的毫秒数 console.log("startTime", startTime); //开始渲染此次更新时的时间戳 console.log("commitTime", commitTime); //提交此次更新时的时间戳,此值在提交的所有 profiler 中共享 }; return ( <Profiler id="myComponentt" onRender={handleReorder}> <MyComponent /> </Profiler> )
- 用
-
使用react developer tools的Profiler选项卡,可以看到和“性能”面板类似的界面,如火焰图,可以直接看到具体的组件并选中