Memory Cache 为什么有时候不生效?

Mr-柯一 阅读 3

我在开发一个图片预览功能,发现有些图片明明已经加载过一次了,但刷新页面后还是重新请求,Memory Cache 没有命中。我用的是 new Image() 动态加载图片,控制台 Network 里看到 memory cache 的状态时有时无,这是为啥?

试过加 Cache-Control: max-age=3600 响应头,但好像对 Memory Cache 没啥影响,是不是只有 Disk Cache 才认这个?

我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
打工人天琪
这个问题我之前也踩过坑,让我来详细说说 Memory Cache 的工作机制,你就能明白为什么会出现这种情况了。

先说结论:Memory Cache 和 Disk Cache 是两个完全不同的层级,刷新页面后 Memory Cache 不命中是完全正常的行为,不是你的代码有问题。

具体来说,Memory Cache 是浏览器进程级别的内存缓存,它的生命周期非常短,只存在于当前页面会话期间。当你刷新页面或者关闭标签页,Memory Cache 基本就没了。你在 Network 面板看到 "memory cache" 那一行,通常是说这个资源直接从内存里拿的,没有走网络请求,但这个状态只在当前页面有效。

你提到的现象——刷新页面后 Memory Cache 没命中——这是预期行为。因为刷新操作本身就会触发浏览器的缓存失效逻辑。F5 刷新时,浏览器会向服务器发送条件请求(带 If-Modified-Since 或 If-None-Match),即使资源在 Disk Cache 里,浏览器也会先验证一下。而 Memory Cache 因为内存被释放,根本就不存在了。

关于 Cache-Control: max-age=3600 这个响应头,你理解得没错,它主要影响的是 Disk Cache(HTTP 缓存),告诉浏览器这个资源可以在磁盘缓存里存多久。Memory Cache 的策略是浏览器自己决定的,不完全受 HTTP 头控制。

不过 Memory Cache 确实有一些特点需要注意:

第一,资源必须完整加载成功才会进入 Memory Cache。如果你的图片请求被中断或者加载失败,是不会被缓存的。

第二,Memory Cache 有容量限制,而且优先级机制很复杂。大图片可能不会被放进 Memory Cache,因为内存太宝贵了。浏览器更倾向于把小资源(比如 JS、CSS、小图标)放在内存里。

第三,使用 new Image() 动态加载时,如果 Image 对象被垃圾回收了,对应的内存缓存引用也可能失效。这是个容易被忽略的细节。

给你一个改进方案,如果你想在页面内复用已加载的图片,可以自己维护一个缓存池:

// 图片缓存池,防止重复加载
const imageCache = new Map();

function loadImage(src) {
// 先查缓存池
if (imageCache.has(src)) {
return Promise.resolve(imageCache.get(src));
}

return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
// 存入缓存池,保持引用
imageCache.set(src, img);
resolve(img);
};
img.onerror = reject;
img.src = src;
});
}

// 使用示例
loadImage('https://example.com/image.jpg').then(img => {
document.body.appendChild(img);
});

// 再次调用同样的 src,直接从缓存池返回
loadImage('https://example.com/image.jpg').then(img => {
console.log('这张图不会重新请求');
});


如果你需要跨页面、刷新后仍然有效的缓存,那就要依赖 Disk Cache 了。确保你的响应头设置正确:

// 服务端响应头示例
// Cache-Control: max-age=31536000 // 一年有效期,适合静态资源
// 或者
// Cache-Control: no-cache, ETag: "xxx" // 每次验证,但不用重新传输


还有一种情况会导致缓存不命中,就是请求 URL 每次都变。检查一下你的图片 URL 是否带了随机参数或者时间戳,比如 image.jpg?t=123456,这种每次都变的 URL 会被浏览器当成不同的资源,自然无法命中缓存。

总结一下:Memory Cache 刷新后不生效是正常的,想持久化缓存得靠 Disk Cache。如果你需要在同一个页面内多次使用同一张图片,建议自己维护一个缓存池,比依赖浏览器的 Memory Cache 更可控。
点赞
2026-03-02 19:15