Memory Cache 为什么有时候不生效? Mr-柯一 提问于 2026-03-02 19:12:18 阅读 3 优化 我在开发一个图片预览功能,发现有些图片明明已经加载过一次了,但刷新页面后还是重新请求,Memory Cache 没有命中。我用的是 new Image() 动态加载图片,控制台 Network 里看到 memory cache 的状态时有时无,这是为啥? 试过加 Cache-Control: max-age=3600 响应头,但好像对 Memory Cache 没啥影响,是不是只有 Disk Cache 才认这个? 缓存优化 我来解答 赞 1 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 1 条解答 打工人天琪 Lv1 这个问题我之前也踩过坑,让我来详细说说 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 加载更多 相关推荐 2 回答 45 浏览 Memory Cache缓存导致动态组件样式残留怎么办? 在做页面切换时用了Memory Cache缓存组件状态,但发现上一个页面的CSS变量样式残留了,比如这个示例: :root { --primary-color: #4CAF50; } .dynamic... 程序猿东成 优化 2026-02-11 22:36:23 1 回答 11 浏览 Cache-Control 设置了却没生效? 我给静态资源加了 Cache-Control,但浏览器还是每次都请求,根本没缓存,这是为啥? 我在 Nginx 里配置了 expires 1y;,也试过直接在 HTML 的 meta 标签里写,但刷新... Mr.树遥 优化 2026-02-26 18:12:22 1 回答 12 浏览 Cache-Control 设置了 max-age=3600,为什么浏览器还是发请求? 我给静态资源加了 Cache-Control: max-age=3600,但每次刷新页面,浏览器还是会发请求到服务器,只是返回 304。不是应该直接用本地缓存、不发请求才对吗? 我用的是 Nginx,... 柯言 ☘︎ 优化 2026-02-25 19:44:18 1 回答 34 浏览 为什么设置了Cache-Control还是频繁请求资源? 我在开发单页应用时给API接口设置了Cache-Control:max-age=30,但发现每次页面刷新都会重新请求JSON数据,明明应该缓存30秒才对。 代码是这样写的:fetch('/a... 志青 Dev 优化 2026-02-16 01:01:32 1 回答 29 浏览 为什么设置了Cache-Control还是频繁发起请求? 大家好,我在优化API请求时设置了Cache-Control:max-age=300,但发现页面刷新时还是频繁发起请求,控制台网络标签也没显示缓存命中的状态。比如获取用户信息的接口,明明30秒内重复访... UP主~新杰 优化 2026-02-13 16:04:32 2 回答 69 浏览 为什么设置了Cache-Control但浏览器还是重新请求资源? 我正在优化网站静态资源加载,按照教程设置了Cache-Control: public, max-age=3600,但发现每次刷新页面时资源都会重新请求。用开发者工具看响应头确实有这个字段,但网络标签显... 晴文 Dev 前端 2026-02-04 10:45:26 1 回答 32 浏览 GitHub Actions的Cache缓存为什么总是显示“Not found”? 我在项目里配置了GitHub Actions的npm缓存,但每次构建时都提示Cache not found for input keys,明明之前成功过几次啊? 场景是这样的:前端Vue项目用npm,... 司空耘郗 工具 2026-02-02 16:11:25 2 回答 90 浏览 为什么用了cache-loader还是每次构建都重新编译? 在Vue项目里按文档把cache-loader加到loader链开头了,但每次运行npm run build都会重新编译所有文件。之前尝试过删掉node_modules和dist目录,甚至改过load... Mr.梓淇 前端 2026-02-02 11:48:32 2 回答 70 浏览 cache-loader在开发环境一直缓存旧代码怎么办? 在项目中配置了cache-loader想提升构建速度,但发现修改代码后页面没变化,必须重启服务才生效。尝试过删除node_modules/.cache目录也没用,控制台没有报错。webpack4的配置... 公孙浩然 优化 2026-01-30 23:49:24 1 回答 449 浏览 Cache-loader 加了反而变慢,是我配置错了吗? 我最近在项目里加了 cache-loader 想提升构建速度,但发现第二次构建比没加还慢,有点懵。 我是在 babel-loader 前面加的,配置大概是这样: module.exports = { ... Des.传志 优化 2026-03-01 18:35:18
先说结论: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 对象被垃圾回收了,对应的内存缓存引用也可能失效。这是个容易被忽略的细节。
给你一个改进方案,如果你想在页面内复用已加载的图片,可以自己维护一个缓存池:
如果你需要跨页面、刷新后仍然有效的缓存,那就要依赖 Disk Cache 了。确保你的响应头设置正确:
还有一种情况会导致缓存不命中,就是请求 URL 每次都变。检查一下你的图片 URL 是否带了随机参数或者时间戳,比如
image.jpg?t=123456,这种每次都变的 URL 会被浏览器当成不同的资源,自然无法命中缓存。总结一下:Memory Cache 刷新后不生效是正常的,想持久化缓存得靠 Disk Cache。如果你需要在同一个页面内多次使用同一张图片,建议自己维护一个缓存池,比依赖浏览器的 Memory Cache 更可控。