网络层面优化
- http2
- 解析速度快。
- 多路复用,多个请求可以共用一个TCP连接。
- 头部压缩,更小的负载体积。
- 静态资源使用CDN
将资源分发到CDN的边缘网络节点,用户请求资源时就近返回节点上缓存的资源,不需要每个用户的请求都回源站获取,避免网络拥塞、缓解源站压力,保证用户访问资源的速度和体验。
- 充分利用http缓存
HTML:使用协商缓存。CSS&JS&图片:使用强缓存,文件命名带上hash值。
- DNS预解析
适用于网页引用了大量其他域名的资源。dns-prefetch需慎用,多页面重复DNS预解析会增加重复DNS查询次数。
// 用meta标签来告知浏览器, 当前页面要做DNS预解析。
<meta http-equiv="x-dns-prefetch-control" content="on" />
// 在页面header中使用link标签来强制对DNS预解析。
<link rel="dns-prefetch" href="https://www.baidu.com/" />
- 自托管第三方资源
第三方资源官方的cdn比较慢的情况下可以考虑自托管三方资源,根据项目实际情况进行使用。
资源体积优化
- 单独打包css及压缩css代码
- webpack默认将js代码和css代码打包到一个文件,可使用mini-css-extract-plugin插件单独打包css会减少整包的体积。
- 可使用css-minimizer-webpack-plugin插件压缩css代码
- 路由懒加载Suspense + React.lazy
- 代码分割optimization.splitChunks
webpack默认会将所有模块代码打包在一起,这种规则的优点是能减少页面的HTTP请求数,缺点是页面初始代码包过大影响首屏渲染性能,无法有效应用浏览器缓存,分包可避免代码修改整个bundle缓存失效。
- 三方依赖单独使用cdn引入,使用externals属性单独配置。
- 压缩代码
如果使用的是webpack v5或更高版本,是开箱自带的功能,如果是v5以下或者希望自定义配置,可安装terser-webpack-plugin实现压缩。
- 开启gzip压缩
- 三方依赖的按需引入
如果直接引入整个插件,会导致项目的体积过大,可以只引入需要使用的内容,以达到减小项目体积的目的。
import lodash -> import lodash/get
- 使用支持Tree Shaking的三方依赖
import lodash -> import lodash-es
- 替换更小的库
使用dayjs替换moment。
- 减少不必要的三方依赖的使用
yarn why查看依赖被引用的情况。可根据项目实际情况减少三方依赖的使用。
- 使用时动态引入模块,不在首页就加载(组件懒加载)
比如xlsx下载文件,在使用的时候再加载。
const buttonClick = async() => {
// 使用时异步引入xlsx模块
const xlsx = await import('xlsx');
xlsx.writeFile(wb, filename)
}
项目内代码层面优化
- 使用iconfont代替图片图标
字体图标就是将图标制作成一个字体,使用时就跟字体一样,可以设置属性例如font-size、color等,非常方便,并且字体图标是矢量图,不会失真。还有一个优点是生成的文件特别小,无论是加载还是打包所消耗的资源都相对较小一些。
- 长列表优化
- 滚动加载更多
- 虚拟列表
- 分页
- 减少DOM的操作,尽可能的合并DOM操作
- 长任务使用Web Workers
- 事件委托
- 合理使用节流防抖
- 骨架屏优化白屏时长
图片优化
- 图片懒加载
当图片出现在可视区域或者即将出现在可视区域时再加载图片,避免一次性加载全部图片。
- 图片压缩
一些图片适当降低图片质量时,通常是看不出来区别的,可以使用image-webpack-loader进行图片压缩。
- 使用webp图片
webp的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha透明以及动画的特性,在JPEG和PNG上的转化效果都相当优秀、稳定和统一。
- 尽量使用CSS代替图片
一些简单的图片效果如果可以通过CSS效果实现则进行用CSS来实现,可以减小请求次数或者打包体积大小。