就我个人而言,性能优化分为三大主要部分,构建工具优化,网络请求优化,渲染优化。
当前前端最常使用的工具是webpack,所以我们要做的第一步就是提高他的构建效率
构建工具优化
多进程构建
webpack 是单线程的,就算此刻存在多个任务,你也只能排队一个接一个地等待处理。这是 webpack 的缺点,好在我们的 CPU 是多核的,Happypack 会充分释放 CPU 在多核并发方面的优势,帮我们把任务分解给多个子进程去并发执行,大大提升打包效率。
使用DllPlugin处理第三方库
DllPlugin 是基于 Windows 动态链接库(dll)的思想被创作出来的。这个插件会把第三方库单独打包到一个文件中,这个文件就是一个单纯的依赖库。这个依赖库不会跟着你的业务代码一起被重新打包,只有当依赖自身发生版本变化时才会重新打包。
删除冗余代码
利用Tree-Shaking去除没被使用的模块
Tree-Shaking基于 import/export 语法,Tree-Shaking 可以在编译的过程中获悉哪些模块并没有真正被使用,这些没用的代码,在最后打包的时候会被去除。
利用UglifyJsPlugin在压缩过程中对碎片化的冗余代码进行自动删除
手动引入 UglifyJsPlugin 的代码其实是 webpack3 的用法,webpack4 现在已经默认使用 uglifyjs-webpack-plugin 对代码做压缩了——在 webpack4 中,我们是通过配置 optimization.minimize 与 optimization.minimizer 来自定义压缩相关的操作的。
按需加载
使用 React-Router来实现组件按需加载
分析构建结果进行体积压缩
使用webpack-bundle-analyzer插件,它会以矩形树图的形式将包内各个模块的大小和依赖关系呈现出来,使文件结构可视化,找出导致体积过大的原因。
网络请求优化
通过两个大方面来进行优化
- 减小请求体积
- 减少网络请求
减小请求体积
关于减少请求体积,在上面webpack中已经都基本包含了,另外,还可以开启Gzip压缩来进一步缩小体积
开启Gzip压缩
只需要你在你的 request headers 加上accept-encoding:gzip
将静态资源放到CDN
将静态资源放到CDN以提升访问速度
合理的处理图片
在合适的场景下选择合适的图片格式
- JPEG/JPG:有损压缩、体积小、加载快、不支持透明,适用于轮播图等大图片。
- PNG:无损压缩、质量高、体积大、支持透明,适用于呈现小的 Logo、颜色简单且对比强烈的图片或背景等。
- SVG:文本文件、体积小、不失真、兼容性好,图片可无限放大而不失真。
- Base64:文本文件、依赖编码、小图标解决方案
- WebP:支持透明,可展示动图,兼容性差。
减少网络请求
CSS精灵图
将多个图标放在一张图片上,通过定位使用对应的图标,从而减少请求次数
使用Base64图片
Base64可以直接将小图标写在代码中,从而减少图标请求。
合理的使用缓存
通过网络获取内容既速度缓慢又开销巨大。较大的响应需要在客户端与服务器之间进行多次往返通信,这会延迟浏览器获得和处理内容的时间,还会增加访问者的流量费用。因此,缓存并重复利用之前获取的资源的能力成为性能优化的一个关键方面。缓存详解请看我之前的文章
渲染优化
渲染方面主要有三个优化方面
- 服务端渲染
- CSS优化
- JS优化
SSR服务端渲染
使用SSR服务端渲染减少首屏白屏的时间,但是他并不是银弹,因为他将原本分散在客户端的压力全都聚集到了服务器,在服务器性能低下时,很可能会得不尝失。
CSS优化
CSS选择器优化
由于CSS选择器是从右向左匹配的,所以我们可以做如下几条优化
- 避免使用通配符,只对需要用到的元素进行选择。,因为他会将所有元素全匹配一遍
- 少用标签选择器。如果可以,用类选择器替代
- 减少嵌套。后代选择器的开销是最高的,因此我们应该尽量将选择器的深度降到最低(最高不要超过三层),尽可能使用类来关联每一个标签元素。
CSS加载顺序优化
由于CSS会阻碍页面渲染,所以需要尽量的将CSS前置。
JS优化
主要的优化方面在于减少回流重绘
用async和defer合理的选择JS的加载时机
- 在正常模式下,js会阻塞浏览器,浏览器必须等待js 加载和执行完毕才能去做其它事情。
- async 模式下,JS 不会阻塞浏览器做任何其它的事情。它的加载是异步的,当它加载结束,JS 脚本会立即执行。
- defer 模式下,JS 的加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded 事件即将被触发时,被标记了 defer 的 JS 文件才会开始依次执行。
当脚本与 DOM 元素和其它脚本之间的依赖关系不强时,选用 async;当脚本依赖于 DOM 元素和其它脚本的执行结果时,选用 defer。
减少回流重绘
- 合并多次DOM操作,尽量将多次DOM操作合并成一次,减少回流或者重绘的性能。例如使用DocumentFragment或者innerHTML
- DOM离线化
- 使用类名去合并样式,而不要一条条的修改
懒加载
利用元素占位,只有当图片到了可视区域内再去拉取图片。
防抖节流
利用防抖节流来减少某些高频事件触发的次数
参考自:前端性能优化原理与实践