Memory Cache 为什么有时候不生效? Mr-柯一 提问于 2026-03-02 19:12:18 阅读 91 优化 我在开发一个图片预览功能,发现有些图片明明已经加载过一次了,但刷新页面后还是重新请求,Memory Cache 没有命中。我用的是 new Image() 动态加载图片,控制台 Network 里看到 memory cache 的状态时有时无,这是为啥? 试过加 Cache-Control: max-age=3600 响应头,但好像对 Memory Cache 没啥影响,是不是只有 Disk Cache 才认这个? 缓存优化 我来解答 赞 8 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 喜静 Lv1 Memory Cache 刷新页面后本来就没了,这东西只存在于当前页面会话期间,页面一刷新甚至一关标签页就清空了,跟 Cache-Control 没关系。 想跨页面缓存图片,有两个方案: 一是用 Service Worker 拦截请求做缓存: // 注册 Service Worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js'); } // sw.js 中缓存图片 self.addEventListener('fetch', event => { if (event.request.url.includes('/images/')) { event.respondWith( caches.open('image-cache').then(cache => { return cache.match(event.request).then(response => { return response || fetch(event.request).then(networkRes => { cache.put(event.request, networkRes.clone()); return networkRes; }); }); }) ); } }); 二是直接用 fetch + Cache API 在当前会话缓存: const imageCache = new Map(); function loadImage(url) { return new Promise((resolve, reject) => { if (imageCache.has(url)) { resolve(imageCache.get(url)); return; } fetch(url, { cache: 'force-cache' }).then(res => { const blob = res.blob(); imageCache.set(url, blob); const img = new Image(); img.src = URL.createObjectURL(blob); img.onload = () => resolve(img); img.onerror = reject; }); }); } 回复 点赞 2026-03-10 21:06 打工人天琪 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 更可控。 回复 点赞 3 2026-03-02 19:15 加载更多 相关推荐 2 回答 54 浏览 Memory Cache 没生效?Vue组件里图片重复请求怎么回事? 我在 Vue 项目里用 img 标签加载同一张图片,按理说浏览器应该走 Memory Cache,但每次切换组件都会重新请求,network 面板里状态是 200 而不是 (memory cache)... Zz子格 优化 2026-03-09 12:28:18 2 回答 75 浏览 Memory Cache缓存导致动态组件样式残留怎么办? 在做页面切换时用了Memory Cache缓存组件状态,但发现上一个页面的CSS变量样式残留了,比如这个示例: :root { --primary-color: #4CAF50; } .dynamic... 程序猿东成 优化 2026-02-11 22:36:23 2 回答 113 浏览 为什么设置了Cache-Control还是没生效? 我在 Nginx 里给静态资源加了 Cache-Control: max-age=31536000,但每次刷新页面浏览器还是会重新请求图片,状态码是 200 而不是 304 或 from disk c... Des.素伟 前端 2026-03-17 12:03:24 1 回答 32 浏览 Cache API 缓存的资源怎么更新不生效? 我在 Service Worker 里用 Cache API 缓存了静态资源,但改了 JS 文件后刷新页面还是加载旧的,明明已经更新了版本号啊。 我试过在 install 事件里换新的缓存名,比如从 ... 若惜~ 前端 2026-03-31 12:10:14 2 回答 44 浏览 PWA中Cache API缓存的资源怎么更新不生效? 我用Cache API在service worker里缓存了静态资源,但改了JS文件后,刷新页面还是加载旧版本。我已经在install事件里用了新的cache名称,也调用了skipWaiting()和... W″奥杰 移动 2026-03-20 22:10:23 2 回答 57 浏览 PWA中Cache API缓存的资源怎么更新不生效? 我在做PWA离线功能,用Cache API缓存了静态资源,但更新文件后刷新页面还是加载旧缓存,试过改cacheName也不行。 service worker里是这样写的: self.addEventL... 小书妍 移动 2026-03-13 04:38:22 2 回答 35 浏览 Cache-Control 设置了 max-age=3600,为什么浏览器还是发请求? 我给静态资源加了 Cache-Control: max-age=3600,但每次刷新页面,浏览器还是会向服务器发请求,只是返回 304。不是应该直接用缓存、不发请求才对吗? 我试过在 Nginx 里配... UX玉萱 优化 2026-03-05 10:59:21 2 回答 40 浏览 Cache-Control 设置了却没生效? 我给静态资源加了 Cache-Control,但浏览器还是每次都请求,根本没缓存,这是为啥? 我在 Nginx 里配置了 expires 1y;,也试过直接在 HTML 的 meta 标签里写,但刷新... Mr.树遥 优化 2026-02-26 18:12:22 1 回答 29 浏览 Cache-Control 设置了 max-age=3600,为什么浏览器还是发请求? 我给静态资源加了 Cache-Control: max-age=3600,但每次刷新页面,浏览器还是会发请求到服务器,只是返回 304。不是应该直接用本地缓存、不发请求才对吗? 我用的是 Nginx,... 柯言 ☘︎ 优化 2026-02-25 19:44:18 2 回答 60 浏览 为什么设置了Cache-Control还是频繁请求资源? 我在开发单页应用时给API接口设置了Cache-Control:max-age=30,但发现每次页面刷新都会重新请求JSON数据,明明应该缓存30秒才对。 代码是这样写的:fetch('/a... 志青 Dev 优化 2026-02-16 01:01:32
想跨页面缓存图片,有两个方案:
一是用 Service Worker 拦截请求做缓存:
二是直接用 fetch + Cache API 在当前会话缓存:
先说结论: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 更可控。