- 从过程趋势来看,
性能优化可分为网络层面和渲染层面; - 从结果趋势来看,
性能优化可分为时间层面和体积层面。
网络层面
- 构建策略:基于构建工具(
Webpack/Rollup/Parcel/Esbuild/Vite/Gulp) - 图像策略:基于图像类型(
JPG/PNG/SVG/WebP/Base64) - 分发策略:基于内容分发网络(
CDN) - 缓存策略:基于浏览器缓存(
强缓存/协商缓存)
构建策略
主要围绕webpack做相关处理
- 减少打包时间:
缩减范围、缓存副本、定向搜索、提前构建、并行构建、可视结构 - 减少打包体积:
分割代码、摇树优化、动态垫片、按需加载、作用提升、压缩资源缩减范围 - 配置include/exclude缩小Loader对文件的搜索范围,好处是
避免不必要的转译。 缓存副本 - 配置cache缓存Loader对文件的编译副本,好处是
再次编译时只编译修改过的文件。 定向搜索 - 配置resolve提高文件的搜索速度,好处是
定向指定必须文件路径。 提前构建 - 配置DllPlugin将第三方依赖提前打包,好处是
将DLL与业务代码完全分离且每次只构建业务代码。 并行构建 - 配置Thread将Loader单进程转换为多进程,好处是
释放CPU多核并发的优势。 可视结构 - 配置BundleAnalyzer分析打包文件结构,好处是
找出导致体积过大的原因。 分割代码 - 分割各个模块代码,提取相同部分代码,好处是
减少重复代码的出现频率。webpack v4使用splitChunks替代CommonsChunksPlugin实现代码分割。 摇树优化 - 删除项目中未被引用代码,好处是
移除重复代码和未使用代码。只对ESM规范生效 动态垫片 - 通过垫片服务根据UA返回当前浏览器代码垫片,好处是
无需将繁重的代码垫片打包进去。每次构建都配置@babel/preset-env和core-js根据某些需求将Polyfill打包进来,这无疑又为代码体积增加了贡献。 按需加载 - 将路由页面/触发性功能单独打包为一个文件,使用时才加载,好处是
减轻首屏渲染的负担。 作用提升 - 分析模块间依赖关系,把打包好的模块合并到一个函数中,好处是
减少函数声明和内存花销。 压缩资源 - 压缩HTML/CSS/JS代码,压缩字体/图像/音频/视频,好处是
更有效减少打包体积。
图像策略
- 图像选型:了解所有图像类型的特点及其何种应用场景最合适
- 图像压缩:在部署到生产环境前使用工具或脚本对其压缩处理
分发策略
- 所有静态资源走CDN:开发阶段确定哪些文件属于静态资源
- 把静态资源与主页面置于不同域名下:避免请求带上
Cookie
缓存策略
- 考虑拒绝一切缓存策略:
Cache-Control:no-store - 考虑资源是否每次向服务器请求:
Cache-Control:no-cache - 考虑资源是否被代理服务器缓存:
Cache-Control:public/private - 考虑资源过期时间:
Expires:t/Cache-Control:max-age=t,s-maxage=t - 考虑协商缓存:
Last-Modified/Etag - 频繁变动资源:设置
Cache-Control:no-cache,使浏览器每次都发送请求到服务器,配合Last-Modified/ETag验证资源是否有效 - 不常变化资源:设置
Cache-Control:max-age=31536000,对文件名哈希处理,当代码修改后生成新的文件名,当HTML文件引入文件名发生改变才会下载最新文件
渲染层面
- CSS策略:基于CSS规则
- DOM策略:基于DOM操作
- 阻塞策略:基于脚本加载
- 回流重绘策略:基于回流重绘
- 异步更新策略:基于异步更新
六大指标
- 加载优化:资源在加载时可做的性能优化
- 执行优化:资源在执行时可做的性能优化
- 渲染优化:资源在渲染时可做的性能优化
- 样式优化:样式在编码时可做的性能优化
- 脚本优化:脚本在编码时可做的性能优化
- V8引擎优化:针对
V8引擎特征可做的性能优化