video标签缓存由服务端响应头决定而非HTML属性;需在Node.js/Express中设置no-store、移除ETag,Nginx中配置expires -1和etag off,并在前端调用load()强制刷新。
video 标签加 cache-control: no-cache 没用浏览器对 的缓存行为不由 HTML 属性控制,而是由服务器返回的 HTTP 响应头决定。即使你在 HTML 里写 ,只要服务端响应头带 Cache-Control: public, max-age=3600,浏览器仍会缓存。关键在服务端配置,不是前端加参数或属性。
在提供视频文件的路由中,必须显式设置响应头,并确保不被后续中间件覆盖。常见错误是只设了 Cache-Control 却漏掉 ETag 和 Last-Modified——这两个字段一旦存在,浏览器可能仍发起条件请求(304 Not Modified),导致“看似没重载实则用了缓存”。
ETag:用 res.removeHeader('ETag')
res.set('Cache-Control', 'no-store, must-revalidate')
?t=xxx 参数,它无法阻止服务端返回可缓存响应头app.get('/video/:id', (req, res) => {
const filePath = path.join(__dirname, 'videos', req.params
.id);
res.removeHeader('ETag');
res.set({
'Cache-Control': 'no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
});
res.sendFile(filePath);
});如果视频走静态文件服务(比如 Nginx 直接 serve /videos/),需在 location 块中覆盖默认缓存策略。注意:不能只写 add_header,必须配合 expires 和 etag off,否则 add_header 可能被忽略或与内置逻辑冲突。
expires -1 表示立即过期(比 0 更可靠)etag off 强制关闭 ETag 生成if ($request_filename ~* \.mp4$) 做条件判断——Nginx 的 if 在 location 内不可靠location /videos/ {
alias /var/www/static/videos/;
expires -1;
add_header Cache-Control "no-store, must-revalidate, max-age=0";
etag off;
}src 并清除 MediaElement 缓存即便服务端配置正确,某些浏览器(尤其是 iOS Safari)对 的 src 切换有内部缓冲机制。单纯改 src 值(如加时间戳)不够,还需调用 load() 并监听 canplay,否则可能复用旧解码器状态。
src 后必须调用 video.load(),不能只靠 DOM 更新load() 导致卡顿;可在 onstalled 或 onerror 时再触发URL.createObjectURL(new Blob(...)) 动态生成视频 URL 后直接播放,会静音或失败const video = document.getElementById('myVideo');
video.src = '/video/clip.mp4?t=' + Date.now();
video.load(); // 必须显式调用
video.addEventListener('canplay', () => {
video.play();
}, { once: true });服务端响应头才是决定性因素,前端加参数只是辅助手段;no-store 比 no-cache 更彻底,而 etag off 和 expires -1 是容易被忽略的硬性配套操作。