前端性能优化
本文最后更新于:2022年5月7日 上午
🏆 记录前端的性能优化方案
资源缓存
资源缓存一般用户缓存静态资源文件,例如: 图片,js文件,css文件等
强缓存
简单理解
如果没有强缓存,则直接向服务器发送请求(类似第一次请求)
如果命中了强缓存,且缓存没有失效,则直接从缓存中取到静态资源
如果命中了强缓存,但是缓存已失效,则进入到协商缓存
优先级权重
Expires
<Cache-Control
<Pragma
强缓存是在客户端向服务端发送get请求时,服务端向客户端响应式,请求头上的Expires
、 Cache-Control
或者 Pragma
来设置的
强缓存又分为 Disk-Cache
(硬盘缓存) 和 Memory-Cache
(内存缓存),存放位置是由浏览器来决定的。
Expires (http 1.0) 
设置的是指定过期时间,客户端准备向服务端发请求的时,会先用本地时间和这个过期时间对比,超过则重新向服务端发请求,这里可能会存在客户端和服务端时间不一致的情况
Cache-Control (http 1.1) (优先级高) 
存的是一个过期的秒,客户端准备向服务端发请求的时,会先判断是否超过这个间隔,如果超过,则重新向服务端发请求。
当与
Expires
同时存在时,Cache-Control
优先级高Pragma 
只有一个值:
no-cache
(优先级最高)当与
Expires
和Cache-Control
同时存在时,Pragma
优先级最高
协商缓存
简单理解
协商缓存生效,服务端返回 304
协商缓存失效,服务端返回200和请求结果
当强缓存没有命中时,则会到协商缓存,协商缓存每次发请求时会带上 last-modified
或者 etag
请求头与服务端协商是否启用缓存,如果服务器返回 304
状态码,则浏览器会从缓存中读取资源
last-modified/ if-Modified-Since (http 1.0)
记录的是该文件最后一次修改该文件的时间,最小单位为秒
当客户端第一次请求服务端的时候,服务端会返回
last-modified
,客户端第二次向服务端发起请求的时候,会将该值作为请求头if-Modified-Since
的值去请求服务端,服务端拿到这个值后会和文件的最后一次修改时间对比,如果一致,则命中协商缓存,返回304
,浏览器从缓存中加载资源ETag / if-None-Match (http 1.1) (优先级高)
记录的是该文件的一串
hash
值,每次文件发生修改,都会计算出一个新的hash
值。当客户端第一次请求服务端的时候,服务端会返回
ETag
,客户端第二次向服务端发起请求的时候,会将该值作为请求头if-None-Match
的值去请求服务端,服务端拿到这个值后会和文件的最后一次的****值对比,如果一致,则命中协商缓存,返回304
,浏览器从缓存中加载资源
Etag
相对于 last-modified
解决了什么问题:
当文件在1秒内发生修改,
last-modified
会错误的返回304
,当文件发生改变,但是文件内容没有发生修改的时候(如:新增了一行,又把这一行删除),last-modified
也会错误的返回304
可参考 图解HTTP缓存
数据缓存
数据缓存一般用于在数据不频繁变动的情况下,我们可以从缓存中读取,减少服务端的压力
常见的三种数据缓存的方案
localStorage
一般用户自定义设置过期时间
存数据的同时需要存一个过期时间,第二次发请求的时候先从缓存中读,如果读到且未过期则使用缓存数据
sesstionStorage
当前窗口关闭时,缓存失效,因为 sesstionStorage 只会在窗口打开到关闭存储,所以当窗口关闭时,数据也会清空 
vuex/redux
单页面
spa
应用一般用于,当页面刷新之前,可以做自定义缓存策略
dns 解析优化
dns 解析一般在 20-120 ms之间,所以当我们一个应用中需要解析的域名过多的话,其实也会对性能有一定的影响,但是我们实际开发中,通常都是做的多服务器部署,把不同的资源放到不同的服务器上如:静态资源服务器,接口服务器等,因为多服务器部署有很多好处
那我们如果一个应用需要 dns 解析的域名过多可以怎么办呢,京东官网就是一个很好的示例,可以在 的里面添加 dns 预解析
<link rel="dns-prefetch" href="//static.360buyimg.com">
<link rel="dns-prefetch" href="//misc.360buyimg.com">
前端层面优化
减少请求次数和请求大小 (合理的对文件进行切割)
静态资源文件压缩 (
webpack
层面对 js,css代码压缩等)启用
gizp
大批量数据分批请求 (分页或上拉加载更多,避免出现一次性返回10万条数据该怎么处理的问题😉)
字体图片和
svg
雪碧图/精灵图
小图片使用
base64
,或者较为重要的图片也使用base64
图片懒加载
资源懒加载 (路由懒加载)
小图片使用
base64
,或者较为重要的图片也使用base64
较为重要的图片也可以使用
preload
,<link rel="preload" as="image" href="https://xxx.com/png" />
图片懒加载
资源懒加载 (路由懒加载)
公共组件按需引入(尽量不使用
require
引入模块)使用 Resource Hints 对资源进行
prefetch
较大的图片根据不同设备来渲染(CDN配合业务具体实现:使用
img
标签srcset/sizes
属性和picutre
标签实现响应式图片,具体可参考文档)尽可能不写内联
css
样式(如果项目需要兼容不同端时,内联的px
会成为致命的问题)静态资源部署到
CDN
,CDN
预热:提前将资源分发到各个节点,避免太多流量打到源站(看具体业务场景)
Vue 优化
生产模式关闭
souceMap
路由懒加载
Webpack 优化
第三方库使用
CDN
 合理的使用
splitchunks
进行文件分割,合理的调整阈值启用
tree shaking
(摇树)webpack 4
版本以上production 模式
默认开启首屏关键 css 进行内联样式设置(内容固定(使用脱离文档流固定宽高),不抖动),可以使用 critters
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。