Skip to content

Latest commit

 

History

History
92 lines (62 loc) · 7.17 KB

浏览器缓存.md

File metadata and controls

92 lines (62 loc) · 7.17 KB

浏览器缓存

浏览器分为 强缓存 和 协商缓存

浏览器在加载资源时,先根据资源的一些 http header 来判断是否命中缓存,强缓存如果命中,直接从浏览器中读取资源,不会发送请求。 当强缓存没有命中,浏览器会发送一个请求到服务器,通过服务器依据资源的另外一些 http header 来判断是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个请求的资源。告诉客户端可以去缓存里面加载这个资源。

共同点:如果命中,都是从客户端加载资源,而不是去服务器加载资源 区别:强缓存不发送请求,协商缓存会发送请求

  1. 强缓存: Expires 和 cache-control 响应头,http的code为200

Expires: 描述一个绝对时间,由服务器返回。 当浏览器第一次发送请求的时候,服务器就会把这个响应头加上 expires 字段。浏览器在接收到这个资源后,会把资源连同请求返回的响应头一起缓存下来。 服务器再次请求资源时,先从缓存寻找,找到这个资源后,直接拿出 expires 与它作比较,没过期就直接命中缓存。如果没命中,浏览器从服务器加载资源时,expires 会再次被更新。

缺点: expires 是一个绝对时间,在服务器与浏览器时差较大时,缓存管理容易出现误差。如果随意修改客户端的时间,就可以影响缓存命中的结果。

cache-control 是一个相对时间,返回的是秒。

当浏览器第一次请求服务器时,会连同资源和请求头一起被缓存下来。 当浏览器再次请求这个资源的时候,拿它第一请求的时间和cache-control设定有效期,计算出一个资源过期的时间,再拿过期时间跟当前的请求作比较,如果请求时间在过期时间之前,就能命中缓存,否则不能因为它设置的事一个相对时间,在进行缓存命中的时候都是拿客户端的时间作比较,要更有效安全一点。 可以同时启用这两个,但是cache-control的优先级更高一点

强缓存的应用

  1. 对于有大量静态页面的网页,一定要利用强缓存提高响应速度,都设置一个超长的 expires 和 cache-control,通常都是针对静态资源 什么是 from disk cache 和 from memory cache 吗,什么时候会触发?
  2. 先查找内存,如果内存中存在,从内存中加载,如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;如果硬盘中未查找到,那就进行网络请求,加载到的资源缓存到硬盘和内存;

协商缓存

当浏览器对于某个资源的请求没有命中强缓存,就会发送一条请求到服务器。验证协商缓存是否命中,如果协商缓存命中,请求响应返回的 http 状态码为 304,并且会有 not-modified 的字符串。

last-modified/if-modified-since 控制协商缓存

  1. 浏览器第一次请求服务器资源时,服务器在返回这个资源的同时,在response的header加上last-modified,这个header表示这个资源在服务器上最后的修改时间。
  2. 浏览器再次发送请求给服务器时,在请求头会加上 if-modified-since,这个值为上次 last-modified 返回的值
  3. 服务器再次收到请求的时候,根据浏览器传过来的 if-modified-since,来判断资源是否有变化,如果没有变化则返回 304 not-modified,不返回资源内容。如果有变化,就正常返回资源内容。当服务器返回 304 时, response header 中不会添加 last-modified 的 header,因为资源既然没有变化。
  4. 收到 304 就会从缓存中加载资源
  5. 如果协商缓存没有命中,浏览器直接从服务器加载资源时,last-modified header 在重新加载时会被更新,下次请求时,in-modified-since 会启用上次 last-modified 的值

etag/if-none-match

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在 response 的 header 里面加上 etag,这个etag是服务器根据当前资源生成的一个唯一标识,这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改的时间没有关系。
  2. 浏览器再次请求这个资源的时候,在请求头加上 if-none-match,就是 etag 的值
  3. 服务器再次收到请求的时候,会把传过来 if-none-match 然后再和新的资源生成新的 etag,如果一样就说明资源没有发生变化,不一样就说明有变化,返回正常的资源内容。
  4. 由于 etag 重新生成过,不管发没发生变化,响应头都会将 etag 返回

区别: last-modified 和 if-modified-since 都是根据服务器时间返回的 header,在没有调整服务器时间和篡改客户端缓存的情况下,这两个 header 配合起来管理很可靠。 但是如果服务器资源其实有变化,但是最后修改的时间没有变化,这种问题不容易被定位出来,当这种情况出现的时候,就会影响协商缓存的可靠性。

【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】一般都是同时启用,这是为了处理Last-Modified不可靠的情况。

注意:分布式系统里面多台文件的last-modified必须保持一致,以免负载均衡到不同的机器导致对比失败。 分布式系统尽量关闭etag 因为每台机器生成的etag不一样 启发式缓存

如果响应中未显示Expires,Cache-Control:max-age或Cache-Control:s-maxage,并且响应中不包含其他有关缓存的限制,缓存可以使用启发式方法计算新鲜度寿命。 通常会根据响应头中的2个时间字段 Date 减去 Last-Modified 值的 10% 作为缓存时间。

缓存的意义就是减少请求,更多的利用本地资源,给用户更好的体验的同时,也可以减轻服务器的压力。最佳实践就是,尽可能命中强缓存,同时能在更新版本的时候让客户端的缓存失效。

如何让用户第一时间使用最新的资源呢?

就是在更新版本的时候,顺便把静态资源的路径改了,这样就相当于第一次访问这些资源,就不会存在缓存的问题了

entry:{
  main: path.join(__dirname,'./main.js'),
  vendor: ['react', 'antd']
},
 output:{
  path:path.join(__dirname,'./dist'),
  publicPath: '/dist/',
  filname: 'bundle.[chunkhash].js'
}

HTML:使用协商缓存。

CSS&JS&图片:使用强缓存,文件命名带上hash值。

不同的hash值也有区别

hash:跟整个项目有关,构建生成的文件hash值都是一样的,只要项目里面有文件更改,整个项目构建的hash值就会更改。

chunkhash:根据不同的入口文件(Entry)进行依赖文件解析,构建对应的chunk,生成对应的hash值

contenthash:由文件内容产生的hash值,内容不同产生的就不同

第一种改了一个文件打包之后其他的hash就都变了,缓存自然全部失效。在实际项目中,一般都会把css文件都抽离出对应的css文件来加以引用,如果使用chunkhash,那么修改了css代码之后,会发现css文件hash值改变的同时,js文件的hash值也会改变,这时候就应该用contenthash

https://github.com/webVueBlog/Leetcode