关于性能优化的9大策略和6大指标

320 阅读10分钟

平时大家认为性能优化是一种无序的应用场景,但在笔者看来它是一种有序的应用场景且很多性能优化都是互相铺垫甚至一带一路。从过程趋势来看,性能优化可分为网络层面和渲染层面;从结果趋势来看,性能优化可分为时间层面和体积层面。

所有的性能优化都围绕着两大层面两小层面实现,核心是网络层面和渲染层面,辅助层面时间层面和体积层面,而辅助层面则充满在核心层面里。

九大策略

网络层面

网络层面的性能优化无疑是如何让资源体积更小加载更快,因此从以下四方面做出建议。

构建策略:基于构建工具(webpack/rollup/parcel/esbuild/vite/gulp)

图像策略:基于图像类型(jpg/png/svg/webp/base4)

分发策略:基于内容分发网络(cdn)

缓存策略:基于浏览器缓存(强缓存/协商缓存)

构建策略

该策略主要围绕webpack做相关处理,说到webpack的性能优化,无疑从时间层面和体积层面入手。

减少打包时间:缩减范围、缓存副本、定向搜索、提前构建、并行构建、可视结构

减少打包体积:分割代码、摇树优化、动态垫片、按需加载、作用提升、压缩资源

缩减范围 配置include/exclude缩小loader对文件的搜索范围,好处是避免不必要的转移,include/exclude通常在各大loader里配置。

缓存副本 配置cache缓存loader对文本的编译副本,好处是再次编译时只编译修改的文件,大部分loader/plugin都会提供一个可使用编译缓存的选项,通常包含cache字眼。

定向搜索 配置resolve提高文件的搜索速度,好处是定向指定必须文件路径。

提前构建 配置DLLplugin将第三方依赖提前打包,好处是将DLL与业务代码完全分离且每次只构建业务代码。

并行构建 配置thread将loader单进程转换为多进程,好处是释放cpu多核并发优势。

可视结构 配置BundleAnalzer分析打包文件结构,好处是找出导致体积过大的原因。从而通过分析原因得出优化方案减少构建时间,BundleAnalzer是webpack官方插件,可直观分析打包文件的模块组成部分、模块体积占比、模块包含关系、模块依赖关系、文件是否重复、压缩体积对比等可视化数据。

分割代码 分割各个模块代码,提取相同部分代码,好处是减少重复代码的出现率。webpack v4使用splitchunks替代commonschunlsplugin实现代码分割

摇树优化 删除项目中未被引用代码,好处是移除重复代码和未使用代码。在webpack里只需将打包环境设置成生产环境就能让摇树优化生效,同时业务代码使用esm规范编写,使用import导入模块,使用export导出模块。

动态垫片 通过垫片服务根据ua返回当前浏览器代码垫片,好处是无需将繁重的代码垫片打包进去。@babel/preset-env提供的usebuiltins可按需导入polyfill。

按需加载 将路由页面/触发性功能单独打包为一个文件,使用时才加载,好处是减轻首屏渲染的负担,所以一般都是一个业务模块共用一个切割模块的注解名称。

作用提升 分析模块间依赖关系,把打包好的模块合并到一个函数中,好处是减少函数声明和内存花销。在webpack里只需将打包环境设置成生产环境就能让作用提升生效或显示设置concatenateModules。

压缩资源 压缩html/css/js代码,压缩字体/图像/音频/视频,好处是更有效减少打包体积。极致的优化代码都有可能不及优化一个资源文件的体积更有效。

图像策略

该策略主要围绕图像类型做相关处理,同时也是接入成本较低的性能优化策略。只需做到以下两点即可。

图像选型:了解所有图像类型的特点及其何种应用场景最合适

图像压缩:在部署到生产环境前使用工具或脚本对其压缩处理

图像选型一定要知道每种图像类型的体积/质量/兼容/请求/压缩/透明/场景等参数相对值,这样才能迅速做出判断在何种场景使用何种类型的图像。

图像压缩可在上述构建策略-压缩资源里完成,也可自行使用工具完成。由于现在大部分webpack图像压缩工具不是安装失败就是各种环境问题,所以还是推荐在发布项目到生产服前使用图像压缩工具处理,这样运行稳定也不会增加打包时间。

图像策略也许处理一张图像就能完爆所有构建策略,因此是一种很廉价但极有效的性能优化策略。

分发策略

该策略主要围绕内容分发网络做相关处理,同时也是接入成本较高的性能优化策略,需足够资金支持。

虽然接入成本较高,但大部分企业都会购买一些cdn服务器,所以在部署的事情上就不用过分担忧,尽管使用就好。该策略尽量遵循以下两点就能发挥cdn最大作用。

所有静态资源走cdn:开发阶段确定哪些文件属于静态资源

把静态资源与主页面置于不同域名下:避免请求带上cookie

内容分发网络简称cdn,指一组分布在各地存储数据副本并可根据就近原则满足数据请求的服务器。其核心特征是缓存和回源,缓存是把资源复制到CDN服务器里,回源是资源过期/不存在就向上层服务器请求并复制到CDN服务器里。 使用CDN可降低网络阻塞,提高用户访问响应速度和命中率。构建在现有网络基础上的智能虚拟网络,依靠部署在各地服务器,通过中心平台的调度、负载均衡、内容分发等功能模块,使用户就近获取所需资源,这就起CDN的终极使命。 基于CDN的就近原则所带来的优点,可将网站所有静态资源全部部署到CDN服务器里。那静态资源包括哪些文件?通常来说就是无需服务器生产计算就能得到的资源,例如不常变化的样式文件、脚本文件和多媒体文件(字体/图像/音频/视频)等

缓存策略

该策略主要围绕浏览器缓存做相关处理,同时也使接入成本最低的性能优化策略。其显著减少网络传输所带来的损耗,提升网页访问速度,是一种很值得使用的性能优化策略。

为了让浏览器缓存发挥最大作用,该策略尽量遵循以下五点就能发挥浏览器缓存最大作用。

考虑拒绝一切缓存策略: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

缓存判断机制

缓存策略通过设置http报文实现,在形式上分为强缓存/强制缓存和协商缓存/对比缓存。

整个缓存机制很明了,先走强缓存,若命中失败才走协商缓存。若命中强缓存,直接使用强缓存;若未命中强缓存,发送请求到服务器检查是否命中协商缓存;若命中协商缓存,服务器返回304通知浏览器使用本地缓存,否则返回最新资源。

有两种较常用的应用场景值得使用缓存策略一试

频繁变动资源:设置cache-control:no-cache,使浏览器每次都发送请求到服务器,配合last-modified/etag验证资源是否有效

不常变化资源:设置cache-control:max-age=31536000,对文件名哈希处理,当代码修改后生成新的文件名,当html文件引入文件名发生改变才会下载最新文件

渲染层面

渲染层面的性能优化,无疑是如何让代码解析更好执行更快,从以下五方面做出建议。

css策略:基于css规则

dom策略:基于dom操作

阻塞策略:基于脚本加载

回流重绘策略:基于回流重绘

异步更新策略:基于异步更新

以上五方面都是编写代码时完成,充满整个项目流程的开发阶段里。

回流重绘策略在渲染层面的性能优化里占比较重,也是最常规的性能优化之一。

css策略

避免出现超过三层的嵌套规则

避免为id选择器添加多余选择器

避免使用标签选择器代替类选择器

避免使用通配选择器,只对目标节点声明规则

避免重复匹配重复重复定义,关注可继承性

dom策略

缓存dom计算属性

避免过多dom操作

使用domfragment缓存批量化dom操作

阻塞策略

脚本与dom/其他脚本的依赖关系很强:对<script>设置defer

脚本与dom/其他脚本的依赖关系不强:对<script>设置async

回流重绘策略

缓存dom计算属性

使用类合并样式,避免逐条改变样式

使用display控制dom显隐,将dom离线化

异步更新策略

在异步任务中修改dom时把其包装成微任务

六大指标

根据性能优化的重要性和实际性划分出九大策略和六大指标,九大策略定位高于六大指标。针对九大策略还是建议在开发阶段和生产阶段接入,在项目复盘时可将六大指标的条条框框实际应用场景接入。

六大指标基本包括大部分性能优化细节,可作为九大策略的补充,根据性能优化建议的特征将指标划分为以下六方面

加载优化:资源在加载时可做的性能优化

执行优化:资源在执行时可做的性能优化

渲染优化:资源在渲染时可做的性能优化

样式优化:样式在编码时可做的性能优化

脚本优化:脚本在编码时可做的性能优化

v8引擎优化:针对v8引擎特征可做的性能优化