# HTTP缓存

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。MDN介绍 (opens new window)

# 强缓存

  • Expires 缓存过期时间
    响应头。值为:日期/时间, 超过设置的时间,缓存过期。配合Cache-Control使用。
  • Cache-Control 缓存控制
    请求头和响应头都支持。用来设置缓存的方式,通过设置不同的值来实现不同的缓存策略。
    • no-store 禁止缓存
    • no-cache 强制确认缓存
      每次发送请求时,都去服务端确认缓存的有效性(请求中带有缓存相关的验证字段)。未过期(返回304),使用本地缓存。
    • private/public 私有和公共缓存
      • 响应头中才有此值
      • public 表示该响应可以被任何中间人(中间代理、CDN等)缓存。
      • private 表示该响应不能被中间人缓存,该响应只能应用于浏览器私有缓存中。(默认值为private
    • max-age=31536000 缓存过期机制
      格式:max-age=seconds,表示资源最多能缓存多久(从发起的时间开始计算)。如果设置了max-age,则Expires会被忽略。
    • must-revalidate 缓存验证确认
      响应头中才有此值。缓存过期后,在向服务器验证状态之前,已过期的缓存将不能被使用。

# 协商缓存

配合Cache-Control: no-cache 使用

# 方式一

  • Last-Modified
    响应头。用来判断缓存是否过期(如果max-age和expires属性都没有,用Last-Modified信息)
  • If-Modified-Since / If-Unmodified-Since
    请求头。把Last-Modified中的值放进此头中,传给服务端,判断缓存是否过期,如果没过期返回304。If-Modified-Since 只能用在GETHEAD请求中。

Last-ModifiedIf-Modified-Since / If-Unmodified-Since要组合使用

# 方式二

  • Etag 数字签名
    响应头。用来判断缓存是否过期。表示资源的版本,一般为hash值。
  • If-None-Match / If-Match 对比签名
    请求头。把Etag的值放进此头中,传给服务端,服务端判断缓存是否过期,如果没过期返回304。

EtagIf-None-Match / If-Match要组合使用。

If-None-Match / If-Match的优先级高于If-Modified-Since / If-Unmodified-Since

# 文件缓存(拓展一下)

HTTP缓存下来的内容,有点缓存在内存中,有的缓存在硬盘

# 内存缓存

特点

  • 读取快速
    内存缓存会将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取。
  • 时效短
    缓存时效性很短,会随着进程的释放而释放
  • 容量小
  • 匹配优先级高

# 硬盘缓存

  • 读取相较于内存缓存慢
    直接将缓存写入硬盘文件中,读取缓存需要对硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢
  • 时效长
  • 容量大
  • 匹配优先级低于内存

# 缓存匹配优先级

Service Worker > 内存缓存 > 硬盘缓存 > 网络请求

# 相关问题

# 浏览器会把哪些文件丢进内存中?哪些丢进硬盘中?

  • 大文件一般是不会存储在内存中的
  • 当前内存使用率高的话,优选存储进硬盘
  • 浏览器会在jsimg等文件解析执行后直接存入内存缓存,而css则会存入硬盘中,所以每次渲染页面都需要从硬盘读取缓存

# 为什么一般js和图片文件会放到内存缓存,css 放在硬盘缓存?

  • css加载一次即可渲染出网页不会来回加载
  • js文件会需要来回调用执行和一些变量值的记录。如果存在磁盘中,来回进行I/O读取开销较大。