共计 2186 个字符,预计需要花费 6 分钟才能阅读完成。
一. 分类
浏览器的缓存,从状态码来看一共有两种
304:确认没有修改
200:不发请求,直接读取缓存
从设置方式来看,有四种(暂不考虑 Service Worker)
maxAge
Application Cache
Last-Modified/If-Modified-Since
Etag/If-None-Match
maxAge
设置方法:
var expires = new Date();
var maxAge = 60*60*24*365;
expires.setTime(expires.getTime() + maxAge * 1000);
response.setHeader(“Expires”, expires.toUTCString());
response.setHeader(“Cache-Control”, “max-age=” + maxAge);
说明:
浏览器在发送请求之前由于检测到 Cache-Control 和 Expires(Cache-Control 的优先级高于 Expires,但有的浏览器不支持 Cache-Control,这时采用 Expires),如果没有过期,则不会发送请求,而直接从缓存中读取文件。Cache-Control 与 Expires 的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过 Cache-Control 的选择更多,设置更细致,如果同时设置的话,其优先级高于 Expires。
备注:
chrome 中只有通过链接跳转访问才可以,f5 是不管用的,’Cache-Control’ is always set to ‘max-age=0′
Application Cache
因为大量的 bug 已经不建议使用,略
Last-Modified/If-Modified-Since
设置方法
fs.stat(realPath, function (err, stat) {
var lastModified = stat.mtime.toUTCString();
var ifModifiedSince = “If-Modified-Since”.toLowerCase();
response.setHeader(“Last-Modified”, lastModified);
if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) {
response.writeHead(304, “Not Modified”);
response.end();
}
})
说明:
response 设置 Last-Modified 头,request 便会带上 If-Modified-Since 头,需要手动比较,并返回 304
备注
Last-Modified 标注的最后修改只能精确到秒级;有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。
Etag/If-None-Match
设置方法
var hash = crypto.createHash(‘md5’).update(file).digest(‘base64’);
response.setHeader(“Etag”, hash);
if (request.headers[‘if-none-match’] && request.headers[‘if-none-match’] === hash) {
response.writeHead(304, “Not Modified”);
response.end();
return;
}
说明:
response 设置 Etag 头,request 便会自动带上 if-none-match 头;需要手动比较,并返回 304 适用于文件更新,但是内容并没有修改的情况,比如目前前端的打包。
流程图
graph TB
start(浏览器请求) –> hasAppcache{appcache?}
hasAppcache — YES –> 200cache[200 从缓存读取]
hasAppcache — NO –> ce{Cache-Control/Expires</br> 是否有效}
ce — YES –> 200cache
ce — NO –> etag{has Etag?}
etag — YES –> ifNoMatch[向服务器请求带 if-None-Match]
etag — NO –> lastModify{has Last-modified?}
lastModify — YES –> hasLastModify[向服务器请求带 if-Modified-Since]
lastModify == NO ==> 200server[200 从服务器读取]
ifNoMatch –> match{match?}
match -. YES .-> 304cache[304 从缓存读取]
match == NO ==> 200server
hasLastModify –> lessThenModifiedSince{lastModified</br><=</br>ifModifiedSince?}
lessThenModifiedSince -. YES .-> 304cache
lessThenModifiedSince == NO ==> 200server
参考文章 https://github.com/etoah/BrowserCachePolicy