Skip to content

性能优化宝典

性能

性能指标

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,节省重复打包

多线程压缩

对于生产环境下的代码压缩,可以使用 TerserPluginparallel 选项来启用多线程压缩

暂时无法在飞书文档外展示此内容

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优化

虚拟列表

基于 MIT 许可发布