浏览器缓存详解

浏览器缓存

缓存位置
  • Service Worker

    • 运行在浏览器背后的独立线程

    • 涉及到请求拦截,所以必须使用HTTPS传输协议

    • 不同点:可以让我们自由控制缓存哪些文件,如何匹配缓存,如何读取缓存,并且缓存是持续性的

    • 工作流程:

      • 注册Service Worker

      • 监听install事件,缓存需要的文件

      • 当用户访问时进行请求拦截,查讯是否存在缓存,存在的话就可以直接读取缓存文件,否则就进行请求数据

    • 当未命中缓存,会调用fetch函数获取数据,也就是根据缓存查找优先级去查找数据。此时无论从哪获取的数据,都会显示是从Service Worker中获取的

  • Memory Cache

    • 内存中的缓存,主要包含当前页面中已经抓取到的资源

    • 比磁盘快,但是缓存持续性很短,会随着进程的释放而释放。

    • 容量有限

    • 在缓存资源时并不关心返回资源的HTTP缓存头Cache Control是什么值

    • 资源的匹配也并非仅仅是对URL的匹配,还可能会对Content-Type,CORS等特征做校验

  • Disk Cache

    • 硬盘上的缓存,读取速度较慢,但是可以存储任何数据

  • Push Cache

    • 推送缓存,是HTTP/2中的内容,当以上三种缓存都没有被命中时才会被使用

    • 只在会话中存在,一旦会话结束就被释放,并且缓存时间很短,并非严格执行HTTP缓存指令

浏览器缓存机制的关键
  • 浏览器每次发送请求,都会现在浏览器缓存中查找该请求的结果以及缓存标识

  • 浏览器每次拿到返回的请求结果都会将该请求结果和缓存标识存入浏览器缓存中

强缓存
  • 不会向服务器发送请求,直接从缓存中读取资源,在谷歌控制台可以看到NetWork选项中该请求返回的200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种HTTP Header实现:Expires和Cache-Control

  • 无法获知服务端数据是否更新

  • Expires

    • 缓存过期时间,用来指定资源到期的时间点。是web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器获取缓存数据

    • http/1的产物,受限于本地时间,如果修改了本地时间,有可能造成缓存失效

  • Cache-Control

    • HTTP/1.1中控制网页缓存的规则

    • 可以在请求头或响应头中被设置,并可以组合多种命令

      • public:表示可以被客户端和代理服务器缓存

      • private:表示响应只能被客户端缓存

      • max-age=30:缓存在三十秒后过期,需要重新请求

      • s-maxage=30:覆盖max-age,只在代理服务器中生效

      • no-store:不缓存任何响应

      • no-cache:资源被缓存,但是浏览器在使用缓存数据时,需要先确认数据是否和服务器的保持一致

      • max-stale=30:30秒内,即使缓存过期,也可以使用该缓存

      • min-fresh:希望在规定时间内获取最新的响应

  • Cache Control优先级高于Expires

  • 面对频繁变动的资源:使用Cache-Control:no-cache

  • 面对不常变化的资源:使用Cache-Control:max-age=246541(很长)

协商缓存
  • 当强缓存失效后,浏览器携带缓存标识向服务器发送请求,服务器根据缓存标识决定是否使用缓存的过程

    • 协商缓存生效,返回304和Not Modified,即服务端数据未更新

      • 浏览器向浏览器缓存发起HTTP请求

      • 请求结果失效,只返回了缓存标识

      • 浏览器携带缓存标识向服务端发送HTTP请求

      • 服务端返回304,该资源无更新

      • 浏览器重新向浏览器缓存中获取该请求的缓存结果

      • 浏览器缓存返回缓存结果

    • 协商缓存失效,返回200和请求结果,即服务端数据已更新

      • 浏览器向浏览器缓存发起HTTP请求

      • 请求结果失效,只返回了缓存标识

      • 浏览器携带缓存标识向服务端发送HTTP请求

      • 服务端重新返回请求结果和200

      • 浏览器将新的请求结果和缓存标识存入浏览器缓存中

    • 通过设置两种 HTTP Header 实现:Last-ModifiedETag

      • Last-Modified:浏览器第一次请求资源时,服务器返回资源的同时,会在response header中添加Last-Modified,值是资源在服务器的最后修改时间,浏览器接收后缓存文件和header

        • 当浏览器下一次请求这个资源时,浏览器检测到Last-Modified这个值,会添加一个If-Modified-Sinceheader,值为Last-Modified的值。

        • 服务器会检查这个If-Modified-Sinceheader是否和当前资源最后修改时间相同,如果相同返回304,不同返回200和新数据

        • 弊端:

          • 如果在本地打开缓存文件,即使没有对文件进行修改,也会造成Last-Modified修改

          • 只能以秒计时,如果在毫秒中修改了文件,服务端还是会认为资源命中了

      • ETag

        • 服务端响应请求时,返回当前资源文件的一个唯一标识,只要资源变化,ETag就会重新生成

        • 浏览器在下一次向服务器发送请求时,会将ETag放在request header里的If-None-Match里,服务端只要比较客户端传来的If-None-Match是否和当前资源的ETag一致

      • Last-ModifiedETag 的对比

        • 后者精确度优于前者

        • 前者性能高于后者,因为前者只需要计算时间,后者需要通过算法计算出一个hash

        • 服务器校验优先考虑后者

用户行为对浏览器缓存的影响

打开网页、地址栏输入地址:查找磁盘缓存Disk cache,如果有缓存则使用,没有则发送请求

普通刷新(F5):并未关闭会话,所以可以先从内存缓存memory cache中查找缓存,如果没有再查找Disk cache

强制刷新(Ctrl+F5):浏览器不使用缓存,因此发送的请求头部带有Cache-Control:no-cache,服务器直接返回200和最新内容

原文地址:https://www.cnblogs.com/ashen1999/p/12671721.html