HTTP:浏览器缓存

本文深入解析浏览器缓存机制,涵盖强缓存与协商缓存的工作原理,对比Last-Modified与Etag的优缺点,探讨Cache-Control指令作用,及在实际项目中如何优化缓存策略,避免常见问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

强缓存(本地缓存)

浏览器在第一次请求资源后,再次请求该资源时,会先获取该资源缓存的header信息,如果命中强缓存,则不继续请求服务端数据,直接使用本地缓存数据,不会与服务器通信、
相关字段
http1.0中使用expirse,用于指定有效期截止时间,如果发送请求的时间在expirse之前就会使用本地缓存
http1.1中使用Cache-Control:max-age=num,num是一个相对值,再次发送请求时会使用资源第一次请求的时间与num相加计算出资源过期时间,再与当前请求时间比较,在过期时间之前则使用本地缓存

协商缓存

由服务器决定是否使用缓存数据,服务器根据相关header字段判定
Last-Modified/If-Modified-Since
(1)第一次请求资源,服务器的response header中会携带 Last-modified标示文件修改时间,
(2)再次请求该资源时request header会使用这个(1)Last-Modified值作为If-Modified-Since的值
(3)服务器在收到If-Modified-Since后会与资源在服务器上的最后修改时间做对比,对比一致则返回304通知浏览器使用本地缓存。
(4)如果服务端没有命中缓存,则正常返回数据,并在reponse header中携带Last-Modified
Etag/If-None-Match
判断过程与Last-Modified类似,不同的是服务端返回304时也会重新生成Etag并携带在reponse header中即使这个Etag没有变化
参考
Last-Modified与Etag
Last-Modified与Etag各有优缺点,根据实际情况选择
Etag解决的问题:

  • 有些周期性修改的文件,只有修改时间改变,文件内容并没有修改,这时我们希望使用的是缓存数据,Last-Modified不能达到需求
  • Last-Modified时间有精度是s级,如果文件在1s内有修改,这是Last-Modified的判断就会失效
  • 有写服务器不能精确计算文件的修改时间

Last-Modified解决的问题:

  • 有写文件生成Etag的代价较大,对性能有影响

Cache-Control

no-store:不使用浏览器缓存
no-catch: 使用协商缓存
max-age: 强缓存
public: 可以被CDN等中间代理缓存
private:仅客户端可缓存

最佳缓存策略

在这里插入图片描述
图片来自google developers

项目中遇到过的问题

强缓存在的问题

项目中存在一个名为pluginA.js的静态文件,pluginA是一个上传的插件
问题:部分用户无法使用上传功能
解决过程:

  1. 首先排查是不是自己使用API的姿势有问题,尝试过后没有发现可疑的点
  2. 有可能是插件本身存在的bug,查看插件issue未找到相关问题,尝试解读源码,并在源码中可能存在问题的地方加入自己的测试代码
  3. 测试时发现测试代码没有生效,进而发现,有问题的用户的pluginA.js是更新之前的版本(pluginA.js曾经修改过)
  4. 查看http请求头,Cache-Control的过期时间设置为一年,而PluginA.js文件一直使用的是6个月前缓存的版本
  5. 考虑到用户并不是计算机相关工作者,6个月不清缓存也是有可能发生的,建议后端将强缓存调整为协商缓存
service worker

问题:一个使用vue-cli搭建的项目,每次上线新功能都需要用户清除缓存才能使用
解决过程:

  1. 首先考虑HTTP缓存了index.html,因为其他js\css等静态文件都是有hash的,不存在缓存的情况

  2. 将HTTP缓存方式修改为协商缓存后,index.html仍然需要清空缓存才能更新

  3. google相关资料,发现浏览器在使用缓存数据时,优先级最高的是service worker中缓存的文件,然后才是HTTP缓存

  4. service worker是由于在项目搭建时开启了PWA,service worker缓存可以在Chrome的开发者工具–>Application–>Cache Storage中查看

  5. service worker中的文件缓存时永久性的,一旦缓存只有两种情况可以清除:1、容量超出限制,浏览器自动清除;2、开发者通过调用API清除

  6. 首先,通过webpack配置关闭service worker(代码如下),但关闭之后仍不能清除service worker中已经缓存的文件

    pwa: {
        serviceWorker: false,
      },
    
  7. 想办法绕开service worker的缓存,使用HTTP缓存,没有找到相关方法,似乎是不可能的,乖乖使用API清除原有缓存

    caches.keys().then(function(names) {
            for (let name of names) caches.delete(name)
          })
    

    vue-cli搭建的项目,在启用PWA后会在src目录下生成registerServiceWorker.js将上面的代码加入registered钩子函数中即可

清空缓存并硬性重新加载可以更新文件------
似乎说明清空缓存会更新service worker缓存的内容
待确认:service worker的数据存储是怎么划分的?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值