前端闲聊系列(4):谈各个方面的性能优化

381 阅读3分钟

这里会从影响web性能的各个方面谈性能优化。

浏览器相关

浏览器主要影响的是渲染过程,因此会从渲染的五个阶段入手。

五个阶段即

  • parse
  • Style calculation
  • Layout
  • Paint
  • Compositing

parse

dom的解析阶段

  • 设置script的defer或async,防止阻塞

Style calculation

这个阶段解析cssom,会为每个元素的每个属性对应一个computed value

  • 降低选择器复杂度

Layout

这个阶段会计算每个元素的坐标,并生成layout tree。

  • dom操作比较耗性能,因此要注意dom的操作
    • 减少dom,使用新的盒子模型,比如flex box
    • 减少dom修改次数,使用DocumentFragment或虚拟dom,减少dom插入,每次插入都是一次宏任务都会引起页面渲染
    • 避免forced synchronous layout造成的卡顿或layout thrashing。一个页面包含两个tree,其中一个表示实际的dom,一个表示内存中被js操作的dom,操作前者很耗费性能,当读取元素样式时会强制元素渲染,即修改实际dom,在执行一系列dom操作时应避免这种情况

compositing

  • 利用willchange或transform: translateZ(0)将需要改动的元素分到单独的层,分层本身就消耗性能,不要对过多元素使用

其他

  • 不同css属性对后面三步会有不同的影响,详见这里,因此要尽量使用影响比较少的操作,比如修改元素位置时可以使用translate,而不是margin等,这样只会影响合成。
  • 节流和防抖
  • 用requestAnimationFrame()执行动画或其他耗时短且高优先级的任务
  • 低优先级或耗时长的任务可以起一个web worker或使用requestIdleCallback()分成多个小计算完成。

V8相关

V8相关优化的背景知识点看这里

  • 按特定顺序添加对象属性(如果是实例一个class,要在构造函数中添加属性),从而共用Shape
  • 不要修改array的property attribute,否则需要另外用字典保存对应元素
  • 修改原型链会造成ValidityCell,乃至对应inline cache无效,如需要应在其他代码执行前修改
  • 防止内存泄漏

网络配置

这部分用来减少网络请求造成的性能问题

  • http2
  • cdn
  • http缓存
  • 本地缓存,比如使用rtk query可以直接使用上次相同参数网络请求的结果

webpack

生产配置

  • 对于大文件代码分割
    • 使用SplitChunksPlugin分割js,MiniCssExtractPlugin分割css,减少单个bundle的体积
    • 使用import()或React.lazy()实现动态加载
    • 使用import时添加内置指令,输出resource hint,包括prefetch和preload
    • 使用external设置lib,将必要依赖的下载交给用户
  • 合并小文件,减少http请求,比如在module.rule中的图片文件type设置为配置为asset,小图片被转化为base64。
  • 压缩文件,使用mode:production会使用TerserPlugin压缩js,还可以使用CssMinimizerWebpackPlugin压缩css
  • tree shaking,利用es module的静态分析,移除没使用的代码,默认会移除export但没使用的模块,使用package.json 的 "sideEffects"属性,可以移除完全是副作用的代码
  • 缓存,设置optimization.runtimeChunk: 'single',提取runtime,optimization.moduleIds: 'deterministic'处理moduleid,配合http缓存
  • 使用include等指定实际需要处理的模块。

开发配置

开发环境侧重于代码修改后的快速响应。

  • cache webpack的dll相关设置已经凉了,取代的是cache选项,默认在内存中缓存,冷启动时比较慢,可以设置缓存在硬盘中,据经验,比不设置cache能快20倍左右。
  • 打包时处理更少的文件,比如设置resolve和babel的相关目录
  • hmr,模块热更新,保留状态,更快响应,原理
  • 编译输出到内存,webpack-dev-middleware

其他