etag 和 last-modified 是 http 响应头字段,由服务端设置、浏览器自动协商,与 html 内容无关;需配合 cache-control 使用,优先用内容哈希生成 etag,确保响应头一致且不被 cdn 覆盖。

ETag 和 Last-Modified 不是 HTML 里写的,而是 HTTP 响应头控制的
很多人一看到“在 HTML 中实现”,下意识去 <meta> 或 script 里加逻辑,这完全走偏了。协商缓存由服务器决定、浏览器自动执行,HTML 文件本身不参与验证过程。你真正要操作的是服务端响应头:ETag、Last-Modified、If-None-Match、If-Modified-Since 全部属于 HTTP 协议层,和 HTML 文档内容无关。
常见错误现象包括:
- 在 HTML 里用
<meta http-equiv="ETag" content="...">—— 这个标签根本不会被浏览器解析为缓存指令 - 用 JavaScript 拼接时间戳写进
lastModified变量再发请求 —— 浏览器不会读这个变量,也不会把它塞进If-Modified-Since - 只配了
Cache-Control: max-age=3600却没设ETag或Last-Modified—— 强缓存过期后直接发完整请求,跳过 304 路径
服务端怎么正确设置 ETag 和 Last-Modified
两者选一个用就行,但优先用 ETag:它比 Last-Modified 更精确,能避免秒级修改冲突、时钟不同步等问题。如果资源是静态文件(如 /static/app.js),推荐用内容哈希生成 ETag;如果是动态生成的内容(如模板渲染页),可用版本号或内容摘要。
示例(Node.js/Express):
app.get('/app.js', (req, res) => {
const file = fs.readFileSync('./app.js');
const etag = '"' + crypto.createHash('md5').update(file).digest('hex') + '"';
res.set({
'Cache-Control': 'max-age=3600',
'ETag': etag,
});
res.send(file);
});
若用 Last-Modified,必须确保文件系统时间可信,且不能依赖 Node.js 的 fs.statSync().mtime 直接转字符串——要调用 .toUTCString():
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
-
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT✅ 正确格式 -
Last-Modified: 2024-10-21T07:28:00.000Z❌ 浏览器可能忽略
浏览器如何触发协商请求?关键看 Cache-Control 配置
只有当强缓存失效后,浏览器才会自动带上 If-None-Match 或 If-Modified-Since 发起条件请求。这意味着你不能只靠 ETag 单独生效,必须配合 Cache-Control 控制生命周期。
典型配置组合:
-
Cache-Control: public, max-age=3600→ 1 小时内走强缓存,不发任何请求 -
Cache-Control: no-cache→ 每次都发协商请求(带If-None-Match或If-Modified-Since),但允许复用缓存体 -
Cache-Control: must-revalidate→ 强缓存过期后必须验证,不允许“擅自”用过期资源
注意:no-store 会彻底禁用所有缓存,ETag 和 Last-Modified 在这种情况下毫无意义。
为什么有时返回 200 而不是 304?检查这几个点
看到资源反复下载、Network 面板里状态码总是 200,说明协商没生效。最容易被忽略的几个原因:
- 服务器返回的
ETag值前后不一致(比如每次请求都重新计算哈希,但内容没变)→ 浏览器认为资源“变了”,拒绝复用 - 响应头里同时存在
ETag和Last-Modified,但服务器逻辑没对齐(例如文件改了但没更新Last-Modified)→ 浏览器按优先级用ETag,结果比对失败 - CDN 或反向代理(如 Nginx)覆盖了原始响应头,删掉了
ETag或重写了Last-Modified→ 查看实际响应头,别只信本地开发环境 - 请求 URL 带了变动参数(如
?v=123或时间戳)→ 浏览器视为全新资源,不复用任何缓存,自然没有协商机会
真正在意协商效果,就别依赖 HTML 里的任何东西;盯着 DevTools 的 Network 标签页,看每个请求的 Request Headers 是否含 If-None-Match,Response Headers 是否返回 304 Not Modified,这才是唯一可信的验证方式。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










