有很多文章都有从理论上讨论什么是协商缓存的,这里就不多做讲解了。这篇文章主要是要从实操入手协商缓存,给读者一个更直观的体验,以深刻理解什么是协商缓存。 原文地址:http://120.79.199.221:8090/archives/ti-yan-yi-xia-shen-me-shi-xie-shang-huan-cun
准备
首先用node建立一个简单的静态资源服务
const express = require("express");
const path = require('path')
const app = express();
const port = 3000;
app.use(
"/",
express.static(path.resolve("./static"), {
lastModified: false,
etag: true,
setHeaders(res) {
res.set("Cache-Control", "no-cache");
}
})
);
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
index.html页面放在static目录中,静态服务准备好后,使用node index.js启动。
首次访问
打开DevTools并访问http://localhost:3000/
可以看到两个响应头:
Cache-Control: no-cache、ETag: W/"112-18170cbb3ef"
- Cache-Control: no-cache: 告诉浏览器将返回的文件缓存起来,但下次访问时还是要询问服务器文件有没有更新
- ETag: W/"112-18170cbb3ef": 返回文件的内容hash,下次重新请求该文件会将这个值带上
再次访问
刷新浏览器
可以看到发生了304重定向,这里的流程是因为服务器告诉浏览器的缓存策略是
Cache-Control: no-cache,就算有缓存也询问下服务器对文件有没有做更新,下面看看它的请求头:
- If-None-Match: 这个请求头带上上次返回的ETag值,服务器收到后进行比对,发现无变化就直接返回304状态告诉浏览器可以直接从缓存取
修改index.html
在index.html中随便改点儿啥,再刷新页面
可以看到状态码又是200了,看看它的请求头和响应头有什么不同?
可以发现请求头的
If-None-Match的hash和响应头的ETag是不一样的。
总结
这里的协商缓存通过ETag / If-None-Match两个请求头/响应头去完成,有时候也会用Last-Modified / If-Modified-Since两个请求头/响应头去完成缓存的协商,如果同时出现的话,前者优先级大于后者。