前端性能优化
本文最后更新于: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 协议,转载请注明出处。