浏览器缓存机制简介

momo314相同方式共享非商业用途署名转载

做web开发的,浏览器缓存这东西,大家应该都比较熟悉了,简略记录下。

服务器通知浏览器缓存某个资源,有两种方式:

  1. 传统且常用的:是通过HttpHeaders通知浏览器,常见的Headers包括:Expires Cache-Control Last-Modified/If-Modified-Since Etag/If-None-Match
  2. HTML5离线缓存Cache Manifest:通过html标签的manifest属性通知浏览器

下面我们逐一说明:

1. Expires

服务器通过此消息头返回一个 Fri,11 Dec 2015 01:25:57GMT 格式的过期时间,通知浏览器在过期时间之前前浏览器可以直接从浏览器缓存取数据,而无需再次请求。此消息头为 HTTP 1.0 时期的产物。

2. Cache-Control

服务器通过此消息头通知浏览器执行相应的缓存策略,当缓存策略生效时,浏览器不会再向服务器发送请求,相比于Expire消息头,他的选择更多样化,可用值如下:

可用值形式 示例 说明
Public Cache-Control: public 指示响应可被任何缓存区缓存。
Private Cache-Control: private 指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。
这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache Cache-Control: no-cache 指示请求或响应消息不能缓存。
no-store Cache-Control: public 用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age Cache-Control: max-age=3600 指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh Cache-Control: min-fresh=3600 指示客户机可以接收响应时间小于当前时间加上指定时间(以秒为单位)的响应。
max-stale Cache-Control: max-stale=3600 指示客户机可以接收超出超时期间的响应消息。
如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息(以秒为单位)。

3. Last-Modified/If-Modified-Since

需要配合 Cache-control 来使用:Last-Modified 消息头通知客户端当前请求的资源的最后修改时间;当通过max-age判断资源已过期,且资源具有Last-Modified声明,则再次向服务器请求此资源时会携带 If-Modified-Since消息头,服务器将根据头If-Modified-Since 与请求资源的最后修改时间进行比对。若资源在If-Modified-Since时间周无修改,则响应HTTP 304且不返回任何body,否则返回最新的资源。

4. Etag/If-None-Match

需要配合 Cache-control 来使用:服务器在响应请求时,通过Etag告知浏览器当前资源在服务器的唯一标识;当资源过期(max-age),且资源具有Etage声明,则再次请求该资源时将携带If-None-Match消息头,其值为 Etag的值。服务器将会对比唯一标识是否匹配,并决定返回304或200。

大家可能会发现,其实 Last-Modified 已经很强大了,为什么还需要 Etag 呢?

其实,Etag主要是为了解决 Last-Modified 难以解决的几个问题,可以算是 Last-Modified 的补充:

  • Last-Modified只能精确到秒级,如果资源在1秒钟内被多次修改,则无法准确声明文件的修改时间
  • 某些资源会被定期重新生成,虽然最后修改时间变了,但资源内容并没有什么变化时,Last-Modified会弃用缓存

5. HTML5离线缓存Cache Manifest

Cache Manifest是HTML5中引入的一种缓存机制,可以帮助构建一个web离线应用,也就是说,被Cache Manifest指定缓存的资源是不需要网络即可使用的。

Cache Manifest 使用基础

  • Cache Manifest是服务器端的一个按照指定格式书写的文本文件
  • manifest文本文件需要配置 MIME-Type为 text/cache-manifest
  • manifest文本文件的建议的扩展名是:*.appcache ,但实际上你可以使用任何扩展名。
  • 启用Cache Manifest时,需要在HTML文档的<html>标签中指定manifest属性,例如:
    <!DOCTYPE HTML>
    <html manifest="demo.appcache">
    ...
    </html>
    

Manifest 文件格式

manifest 文件可分为四个部分:

  1. CACHE MANIFEST CACHE MANIFEST必须位于文件第一行,这是一个固定格式
  2. CACHE 这是一个必需的节点,在此标题下列出的文件将在首次下载后进行缓存
  3. NETWORK 可选节点,在此标题下列出的文件需要与服务器的连接,且不会被缓存
  4. FALLBACK 可选节点,在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)

下面是一个完整的manifest文件示例:

CACHE MANIFEST
# 2015-12-13 v1.0.0

CACHE:
/common.css
/logo.png
http://momo314.3000ways.com/scripts/jquery-2.1.4.min.js
/error/404.html

NETWORK:
payment.aspx

FALLBACK:
/private/ /error/404.html

下面我们分析一下上面的manifest文件:

  1. 第一行为CACHE MANIFEST
  2. 第二行建议保留为注释行,注释行以#开始
  3. CACHE节点,指定缓存了3个资源文件,这3个文件在首次下载后将被缓存,后续使用时不会再从网络获取
  4. NETWORK节点,指定了payment.aspx页面将始终从网络获取,这也意味着在离线状态下,这个页面是不可用的
  5. FALLBACK节点,指定在private目录下的资源无法访问时,将使用/error/404.html来代替他
  6. 在缓存配置中既可以试用相对路径,也可以使用绝对路径
  7. NETWORK节点可以使用通配符 * 来指定所有资源都必须联网访问,如下所示:
    NETWORK:
    *
    

Manifest 缓存更新

Manifest缓存的更新方式有3种:

  1. 直接更新manifest文件,这也是我们为什么把第二行留为注释行的原因,如果你改了一个js文件的内容,但是文件名并没有改动,可以直接修改注释行来更新缓存
  2. 通过javascript调用 HTML5 API window.applicationCache.update(); 来更新
  3. 清除浏览器缓存,不多说了,这种方法怎么都挡不住,最管用了。。。

Manifest 缓存注意事项

  • 浏览器对缓存数据的容量是有限制的(某些浏览器设置的限制是每个站点 5MB),所以不要缓存太多噢。
  • 如果manifest文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续全部使用老的缓存。
  • 引用manifest的html必须与manifest文件同源,在同一个域下。
  • FALLBACK中的资源必须和manifest文件同源。
  • 当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。
  • 站点中的其他页面即使没有设置manifest属性,请求的资源如果在缓存中也从缓存中访问。
  • 当manifest文件发生改变时,资源请求本身也会触发更新。
✎﹏ 本文来自于 momo314和他们家的猫,文章原创,转载请注明作者并保留原文链接。