前端缓存那些事

前端缓存指的是,浏览器对服务器最近请求过的资源进行存储,经过这种方式来达到减小与服务器的交互请求,以此减小对带宽流量的浪费,以及减小了服务器的负担,而浏览器缓存主要分为两种,强缓存和协商缓存html

1.强缓存

强缓存所谓的“强”,在于强制让浏览器按照必定时间范围内来存储来自服务器的资源,有点强制的味道~,强缓存是利用Expires或者Cache-Control,不发送请求,直接从缓存中取,请求状态码会返回200(from cache)前端

1.1 Expires(已逐步淘汰)

Expires是HTTP/1.0中说起的,让服务器为文件资源设置一个过时时间,在多长时间内能够将这些内容视为最新的,容许客户端在这个时间以前不去检查,MDN 具体介绍 点此vue

  • 指定到期时间

指定缓存到期GMT的绝对时间,若是expires到期须要从新请求webpack

Expires:Sat, 09 Jun 2020 08:13:56 GMT
复制代码

1.2 Cache-Control(主要)

相比上一小节讲的 expires,二者有什么区别呢? Cache-Control 你能够理解成为高级版expires,为了弥补Expires的缺陷在Http1.1协议引入的,且强大以外优先级也更高,也就是当Expires和Cache-Control同时存在时,Cache-Control 会覆盖Expires的配置,即Cache-Control ( Http 1.1 ) > Expires ( Http 1.0 )nginx

Cache-Control 比Expires比较要内涵,具有更多的属性,其中包括以下web

• no-cache :能够在本地缓存,能够在代理服务器缓存,须要先验证才可以使用缓存算法

• no-store : 禁止浏览器缓存,只能经过服务器获取前端工程化

• max-age : 设置资源的过时时间(效果与expires同样)api

例子演示:浏览器

// 设置缓存时间为1年
Cache-Control: max-age=31536000
Expires:Sat, 09 Jun 2020 08:13:56 GMT //同时设置两个,Expires会失效
复制代码

则意味着浏览器能够缓存一年的时间,无需请求服务器,同时若是同时声明Expires和Cache-Control,Expires将失效

🤔️你可能会有疑惑Cache-Control no-cache与max-age=0有什么区别?

本质上就是你按浏览器刷新与强制刷新的区分,看下一节

1.3 用户对浏览器的操做

相信你离不开的操做就是F5(刷新按钮),可是不一样的刷新操做意味着不一样的反应

• Ctrl + F5 (强制刷新)::request header多了cache-control: no-cache (从新获取请求)

• F5 (刷新)/ctrl+R刷新::request header多了 cache-control: max-age=0 (须要先验证才可以使用缓存,Expires无效)

2.协商缓存

协商缓存,就没有强缓存那么霸道,协商缓存须要客户端和服务端两端进行交互,经过服务器告知浏览器缓存是否可用,并增长缓存标识,“有事好好商量”,二者都会互相协商。 协商缓存,其实就是服务器与浏览器交互过程,通常有两个回合,而协商主要有如下几种方式:

2.1 Last-Modified (Http 1.0)

• 第一回合:当浏览器第一次请求服务器资源时,服务器经过Last-Modified 来设置响应头的缓存标识,把资源最后修改的时间做为值写入,再将资源返回给浏览器

• 第二回合:第二次请求时,浏览器会带上 If-Modified-Since 请求头去访问服务器,服务器将 If-Modified-Since 中携带的时间与资源修改的时间对比,当时间不一致时,意味更新了,服务器会返回新资源并更新Last-Modified,当时间一致时,意味着资源没有更新,服务器会返回304状态码,浏览器将从缓存中读取资源

//response header 第一回合
Last-Modified: Wed, 21 Oct 2019 07:28:00 GMT

//request header 第二回合
If-Modified-Since: Wed, 21 Oct 2019 07:29:00 GMT 
复制代码

2.2 Etag (Http 1.1)

MDN中提到ETag 之间的比较,使用的是强比较算法,即只有在每个字节都相同的状况下,才能够认为两个文件是相同的,而这个hash值,是由对文件的索引节、大小和最后修改时间进行Hash后获得的,并且要注意的是分布式系统不适用,了解更多点我

• 第一回合: 也是跟上文同样,浏览器去请求服务器资源,不过此次不是经过Last-Modified了,而是用Etag来设置响应头缓存标识。Etag是由服务端生成的,而后浏览器会将Etag与资源缓存

• 第二回合: 浏览器会将 Etag 放入 If-None-Match 请求头中去访问服务器,服务器收到后,会对比两端的标识,当二者不一致时,意味着资源更新,会从服务器的响应读取资源并更新Etag,浏览器将从缓存中读取资源,当二者一致时,意味着资源没有更新,服务器会返回304状态码,浏览器将从缓存中读取资源

//response header 第一回合
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

//request header 第二回合
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
复制代码

对比完 Last-Modified 与 Etag,咱们能够很显然看到,协商缓存每次请求都会与服务器发生“关系”,第一回合都是拿数据和标识,而第二回合就是浏览器“咨询”服务器是否资源已经更新的过程。

同时,若是以上两种方式同时使用,Etag 优先级会更高,即 Etag( Http 1.1 ) > Last-Modified ( Http 1.0 )

3.缓存状态码

3.1 状态码200 OK(from cache)

这是浏览器没有跟服务器确认,直接用了浏览器缓存,性能最好的,没有网络请求,那么什么状况会出现这种状况?通常在expires或者 Cache-Control 中的max-age头部有效时会发生

3.2 状态码304 Not Modified

是浏览器和服务器“交流”了,肯定使用缓存后,再用缓存,也就是第二节讲的经过Etag或Last-Modified的第二回合中对比,对比二者一致,则意味资源不更新,则服务器返回304状态码

3.3 状态码 200

以上两种缓存全都失败,也就是未缓存或者缓存未过时,须要浏览器去获取最新的资源,效率最低 一句话:缓存是否过时用:Cache-Control(max-age), Expires,缓存是否有效用:Last-Modified,Etag

4.缓存的应用

讲述缓存在咱们开发中最多见的使用

4.1 Vue中缓存的应用

• keepAlive

vue官方文档提到,当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以免反复重渲染致使的性能问题,这个时候咱们但愿那些标签的组件实例可以被在它们第一次被建立的时候缓存下来,咱们能够用一个 元素将其动态组件包裹起来 官方文档🚀

主要用于保留组件状态或避免从新渲染,也意味着不会再走mounted,beforeDestroy函数,组件将被缓存,不用销毁从新渲染,性能比较好

路由的选择性缓存

// router.js
export default new Router({
routes:[
   { path: '/test',
    name: 'test',
    component: () => import('@/views/test/test.vue'),
    meta: {
      title: '测试',
      keepAlive: true
    }
  },
  
 // App.vue
 <keep-alive v-if='$route.meta.keepAlive'>
   <router-view></router-view>
</keep-alive>
 <router-view v-if='!$route.meta.keepAlive'></router-view>
复制代码

组件缓存

<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>
复制代码
  • 打包加入hash

前端工程化开发,可使用 Webpack 编译,打包的资源文件路径里自动带有一串随机字符串,称为 hash

在vue cli脚手架中,咱们能够经过配置vue.config.js(本质上是配置webpack)来设置编译生成的文件具有hash值,意味着每次打包编译的文件都是惟一的,来防止由于缓存,致使资源没有更新,官方文档🚀

Vue-Cli 3x版本

// vue.config.js
module.exports = { 
  filenameHashing: true,
  chainWebpack: (config) => {
      config.output.filename('[name].[hash].js').end();
  }
}
复制代码

4.2 Nginx的缓存

• 配置expires

假设我想经过web应用的图片缓存一周,那你能够在nginx中配置以下👇,配置完以后一周以内的资源只会访问浏览器的资源,而不是去请求Nginx

location ~ \.(gif|jpg|jpeg|png)$ {
          root  /var/mywww/html/public/
          expires 7d;  //表示把数据缓存7天,d:天,s:秒,m:分
  }
复制代码
  • 设置 etag
location ~ \.(gif|jpg|jpeg|png)$ {
          root  /var/mywww/html/public/
          etag		off;  // 默认是开启 on
  }
复制代码

更多的Nginx学习,能够看我上一篇 《Nginx的那些事》

欢迎指出问题~

相关文章
相关标签/搜索