和浏览器较量缓存的有效/刷新时机已经很久了,看起来目前取得了比较完美的表现。
目前对一篇文章返回了以下头部字段:
1 2 3 |
|
从上往下:
-
Last-Modified
只表示文章本身最后的修改时间。早期的时候我只用有这个,但是明显不够用。比如博客的主题发生了变化时,页面也应该算更新。 为了不改变这个字段本身的含义,我使用了 ETag 字段。
-
ETag
实体标签,另一种用来表示实体有没有修改过的方式,是对Last-Modified
的补充。它就是个普通的字符串,内容可以自己写。我上面的格式是:
${GitCommit}-${主题修改时间/系统启动时间}-${文章内容修改时间}-${评论更新时间}
。很复杂吧?其中任何一个的更新都会导致页面缓存失效。
-
Cache-Control
缓存控制。控制缓存保留的时长、刷新策略。max-age
表示缓存多久算新鲜,不新鲜就算过时了(过时不代表不可用)。 后面的must-revalidate
表示对于过时的内容,必须重新检查是否还可用(也就是 304 状态码检测)。不知道我对于我设置的这个值是否完全理解,我的需求是:缓存你随便保存多久,但是总是帮我 revalidate 一下就行。如果不设置为 0,浏览器可能并不会 revalidate。但是设置为 0 我又不知道浏览器会不会不要缓存总是立即删除。
但是目前看起来不会删除,如果 revalidate 后还有效,会继续用。
以上的缓存控制只是针对文章主 HTML 本身(即 Document)。资源文件(Js/Css)我加了一个较短的 max-age
。
如果换成给资源文件 URL 加上版本号的方式,理论上,可以把缓存有效期设置成永远。
本地开发的过程中,如果只是对主题本身进行了修改(而不是文章),比如样式和字体,此时需要刷新。如果没有 ETag,简单的做法是强制刷新,但是,强制刷新会使字体文件也没必要地全部重新加载、页面还会回到页首!这是非常不能忍的。不强制刷新的话,页面的滚动位置会保持一致。这对于观察样式的细微修改会很舒服的。