You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Service Worker离线缓存问题:将缓存的HTML文件加载到object元素中时,内嵌图片无法加载

Service Worker离线缓存问题:将缓存的HTML文件加载到object元素中时,内嵌图片无法加载

这确实是可以实现的,问题大概率出在资源URL匹配或者Service Worker的请求处理逻辑上。我来帮你一步步排查和修复:

一、先验证缓存是否正常工作

首先咱们得确认所有需要离线访问的资源都已经被正确缓存了:

  1. 打开Chrome开发者工具(F12),切换到「Application」标签页
  2. 展开左侧的「Cache Storage」,找到你定义的offline-cache-v6缓存
  3. 检查里面是否包含/app/img.png(以及其他三个资源):
    • 如果图片不在缓存里,说明安装阶段缓存失败了,可能是路径写错,或者在线时资源加载失败
    • 你可以在install事件里加个错误日志,方便排查:
      self.addEventListener('install', event => {
        event.waitUntil(
          caches.open(CACHE_NAME)
            .then(cache => cache.addAll(ASSETS_TO_CACHE))
            .catch(err => console.error('缓存安装失败:', err))
        );
      });
      

二、确保资源请求URL与缓存键完全匹配

这是最常见的坑:请求的URL必须和你缓存数组里的路径完全一致,包括开头的斜杠和目录结构。
比如如果你的实际文件结构是这样的:

你的网站根目录/
├─ index.html
├─ page.html
├─ service-worker.js
└─ img.png

那你之前写的/app/img.png就是错误的,应该改成/img.png(绝对路径)或者img.png(相对路径),同时更新缓存数组:

const ASSETS_TO_CACHE = [
    '/index.html',
    '/page.html',
    '/service-worker.js',
    '/img.png'
];

并且把page.html里的图片路径改成对应的值:

<img src="/img.png" alt="Cached Image" width="300">

三、优化Service Worker的请求处理逻辑

你当前的fetch事件逻辑有两个潜在问题:

  1. 对response.type !== 'basic'的判断可能会过滤掉一些合法的同源资源(虽然理论上同源请求的type都是basic,但某些场景下比如object内的请求可能会有例外)
  2. 离线且缓存没命中时,没有 fallback 处理,直接返回网络错误

修改后的fetch事件逻辑会更健壮:

self.addEventListener('fetch', event => {
  // 跳过非HTTP/HTTPS的请求(比如chrome扩展的请求)
  if (!event.request.url.startsWith('http')) {
    return;
  }

  event.respondWith(
    caches.match(event.request)
      .then(cachedResponse => {
        // 优先返回缓存的资源,不管在线还是离线
        if (cachedResponse) {
          return cachedResponse;
        }

        // 在线时请求网络,成功后缓存新响应
        return fetch(event.request)
          .then(networkResponse => {
            // 只缓存成功的响应(状态码200-299)
            if (networkResponse && networkResponse.status >= 200 && networkResponse.status < 300) {
              const responseToCache = networkResponse.clone();
              caches.open(CACHE_NAME)
                .then(cache => cache.put(event.request, responseToCache));
            }
            return networkResponse;
          })
          .catch(() => {
            // 离线且缓存没命中时,给图片请求返回一个占位图(可选)
            if (event.request.destination === 'image') {
              return new Response(
                'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjRjNGNEY2Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtc2l6ZT0iMTQiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0iQXJpYWwiPkluZmluaXRhbCBJbWFnZTwvdGV4dD48L3N2Zz4=',
                { headers: { 'Content-Type': 'image/svg+xml' } }
              );
            }
          });
      })
  );
});

四、更新Service Worker并验证

  1. 把缓存名称改成新的(比如offline-cache-v7),这样浏览器会识别到Service Worker有更新,触发新的安装流程
  2. 在线打开index.html,等待新的Service Worker注册并安装完成
  3. 切换到离线模式(开发者工具->Network->勾选Offline)
  4. 点击按钮加载page.html,此时图片应该能正常显示了

备注:内容来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 08:25:28