全方位浅谈浏览器缓存

538 阅读4分钟

简述

  • 浏览器缓存即 http 缓存,将请求过的数据(html、css、js)存在浏览器(本地磁盘)中,当再次访问这些资源时可以从本地直接加载,减少服务端请求
  • 服务端通过设置 http 响应头来决定缓存策略(缓存方式)

缓存流程

  • 第一次请求需要的资源,服务器返回资源的同时在 response hearder 响应头中添加了缓存策略,告诉浏览器缓存规则(比如以何种方式缓存,缓存信息......),此时就进行缓存了
  • 第二次如果是请求相同资源,那么就会检查缓存里面是否有相应资源,有的话直接取用,具体方式请看后续

缓存位置

  • 先谈谈缓存都会存在哪,然后引出缓存方式进一步说明

Service Worker

  • 可以让我们自由控制缓存哪些文件、如何匹配/读取缓存,并且缓存是持续性的
  • 离线缓存调用的就是 Service Worker

Memory Cache

  • 内存中的缓存,关闭页面就会失效

Disk Cache

  • 硬盘中的缓存
  • 资源存进硬盘的情况
    • 大文件(大概率)
    • 此时内存利用率较高

Push Cache

  • 推送缓存:以上三种缓存都没命中时,才启用
  • 它只在会话(Session)中存在,会话结束就会释放,缓存时间很短

如果以上四种缓存都没被命中,就只能发起请求了。所以为了性能考虑,选择好缓存方式极为重要

缓存方式

  • 缓存方式就两种
    • 强缓存(默认优先)
    • 协商缓存(协商,也就是商量的意思)
  • 先介绍一个响应头中重要的值 Cache-Control,用于控制网页缓存,有如下主要取值
    • public:响应可以被客户端和代理服务器缓存
    • private(默认取值):响应只有客户端可以缓存
    • no-cache:直接进入协商缓存阶段
    • no-store:不进行任何缓存
    • max-age = xxx(xxx 代表数字):缓存内容在 xxx 时间后失效,单位为秒
    • must-revalidate:如果缓存失效,必须校验正确后才能使用,某些特殊情况客户端是可以使用过期缓存的,比如校验请求发送失败的时候
  • 浏览器查看响应头的方法(新版 edge 为例):右键选择 “检查”,进入开发者模式,选择 “网络” ,选中具体选项(如果没有可以 f5 刷新页面),点击 “标头”

响应头查看.png

强缓存

  • 概念:检查强缓存,不发送 http 请求直接从缓存里读取资源。一般强缓存都会设置有效时间,过期就失效
  • 触发条件(响应头)
    • Expires:一个 GMT 格式的时间字符串(时间戳)。服务器返回该请求结果缓存的到期时间,再次发送请求时,如果未超过则直接使用缓存。缺点是判断是否过期用的是本地时间,本地时间可以自己修改
    • Canche-Control:优先级最高。设置 max-age=xxx 用来替代 Expires,其为相对时间,未过期即可
    • Pragma:取值为 no-cache,等同 Cache-Control 取值 no-cache

协商缓存

  • 概念:需要携带缓存标识(tag)发送 http 请求,由服务器判断是否使用缓存。服务端会进行判断,若资源已发生变化,则返回新资源,否则告诉浏览器启用缓存即可
  • 触发条件(两个)
    • 强缓存过期
    • Cache-Control 的值包含 no-cache
  • 缓存标识由头 Last-Modified/If-Modified-Since、ETag/If-None-Match 决定
    • Last-Modified 返回资源文件在服务器最后的修改时间。浏览器再次请求时,If-Modified-Since 携带上次 Last-Modified 的值,到服务端与最后被修改的时间做对比,若时间小于服务端最后修改时间,则代表资源已变更,重新返回资源,状态码为 200,反之状态码为 304,代表缓存可用
    • ETag 返回当前文件的一个唯一标识符(服务器生成),再次请求时 If-None-Match 会携带 Etag 的值,与服务端的 Etag 值比较,若不一致,则返回新资源,状态码为 200;反之则继续使用缓存,状态码为 304

用户操作对缓存的影响

  • 地址栏输入网址:浏览器会查找缓存,有则直接拿来用
  • 点击刷新按钮或按 f5 刷新:会使用缓存,请求头添加If-Modify-Since字段,如果资源未过期则命中缓存,服务端返回 304 状态码
  • ctrl+f5 刷新:跳过缓存,直接请求新资源,请求头携带Cache-Control: no-cache, Pragma: no-cache字段