性能优化宝典
性能
性能指标
RAIL模型衡量性能
Response
50ms内处理事件:虽然100ms即可达到及时交互的体验,但是其他任务也会有执行时间,加上下一个输入交互也在排队中,所以需要50ms内处理事件。
Animation
10ms内生成帧:虽然1帧预算16ms,但是浏览器渲染需要6ms,因此流畅的体验需要控制在10ms生成1帧。
Idle
尽可能加大空闲时间以提高50ms内响应用户操作的几率。
Load
5s内交付内容并实现可交互,后续加载页面控制在2s内。
页面渲染流程
内存
常见问题
内存膨胀
现象:内存使用过多,表现为网页性能一直很糟糕。
排查:内存上限的衡量受限于设备性能,需要收集用户喜欢使用的设备机型,在目标机型上进行网页体验测试,如体验不佳则存在内存使用过多。
内存泄漏
现象:网页性能随着使用时间越来越差。
排查:查看JS堆内存使用,关注垃圾回收节点,JS内存持续增长或DOM不符合预期的持续增长,则存在内存泄漏。
频繁垃圾回收
现象:网页出现延时或经常暂停。垃圾回收期间所有脚本都会暂停。
排查:观测到内存使用的频繁上升下降则存在频繁垃圾回收。
内存分析
Chrome任务管理器查内存量
Chrome-更多工具-任务管理器
如果没有javascript内存需要右击开启
内存占用空间 :操作系统内存,DOM节点就存储在操作系统里。此值增大说明正在创建DOM
javascript内存 :JS堆内存,实际大小表示可访问对象正使用的内存。此值增大说明正在创建对象或对象正在增长
JS查看内存
window.performance.memory
- jsHeapSizeLimit:JS堆栈内存大小限制
- totalJSHeapSize:包括任意对象和空闲内存的JS堆内存
- usedJSHeapSize:包括v8对象的所有JS对象的堆内存
Performace monitor监控内存量
Performance录制内存变化
勾选Memory后开始录制,点按“扫把图标”强制垃圾回收,可测试内存泄漏等问题
Memory查看内存情况
堆快照 Heap snapshot
当前内存使用情况快照,可以筛选“Detached”已分离DOM节点(js引用导致无法回收的DOM节点)造成的内存泄漏,排查选中的节点被什么位置的什么变量引用
- Shallow Size:浅层大小,对象本身内存大小(不包含内部引用的其他内存)
- Retained Size:保留大小,对象完整的内存大小(包含内部引用内存)
Comparison
两个快照之间可以使用comparison视图比对变化
- New:新创建的对象个数。
- Deleted:删除的对象个数。
- Delta:发生变化的对象个数,净增数。
- Alloc.Size:已分配的内存。
- Freed Size:新对象释放出的内存。
- Size Delta:发生变化的内存,净增内存。
分配时间线 Allocations on timeline
录制新内存分配情况,关注分配时间段的内存具体数据,查找对象被分配到的位置
分配采样 Allocation sampling
按js函数查看分配情况
已分离元素 Detached elements
查看确切的已分离DOM节点和数量
排查频繁垃圾回收
任务管理器和Performance如果观测到频繁的内存上升下降,则是频繁垃圾回收
网络资源优化
网络
请求体压缩
暂时无法在飞书文档外展示此内容
静态资源优化
图片优化
项目工程优化
webpack优化
构建速度优化
持久化缓存
Webpack 4 自身并不直接提供内置的持久化缓存功能,但可以通过配置 cache
选项或者借助第三方插件实现
- 内置缓存配置:可以设置
cache.type
为'memory'
或'filesystem'
来控制是否启用内存缓存或文件系统缓存。对于持久化缓存来说,我们应该选择'filesystem'
。
暂时无法在飞书文档外展示此内容
- hard-source-wepack-plugin:它可以创建更复杂的缓存逻辑,包括跨不同构建之间共享缓存。
暂时无法在飞书文档外展示此内容
DllReferencePlugin三方库处理
DllReferencePlugin:先将常用的大型三方库打包成dll,再通过webpack.DllReferencePlugin引用dll,节省重复打包
多线程压缩
对于生产环境下的代码压缩,可以使用 TerserPlugin
的 parallel
选项来启用多线程压缩
暂时无法在飞书文档外展示此内容
thread-loader多线程
将任务分配给多个 worker 线程的 loader。它适合那些耗时较长的任务,比如 JavaScript 文件的转译(通过 Babel)、样式文件的处理等
暂时无法在飞书文档外展示此内容
cache-loader缓存
可以缓存任何 loader 的结果,这样在下次构建时如果输入没有变化就可以直接使用缓存。这对于大型项目来说非常有用
暂时无法在飞书文档外展示此内容
打包体积优化
Tree Shaking 消除未使用的代码
optimization.splitChunks 代码分割,也可以动态import()
代码优化
React
memo/pure组件
useMemo,useCallback
避免使用匿名函数
延迟加载组件React.lazy,React.Suspence
渲染优化
React DevTools
Profiler面板记录组件触发的每次commit和render时间,辅助发现不合理的commit排查优化的位置
Components面板可查看组件的状态数据,检查数据是否正确
通过插件排查解决了生成封面的合理时机,删除冗余的组件更新,达到减少commit和不必要render的成效,提升了组件平均27%更新时间
JS优化
虚拟列表