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

PWA离线缓存优化咨询:900项静态资源安装过慢问题

大资源量PWA离线缓存优化问题

我有一个需100%离线可用的PWA,包含400个HTML页面、450张PNG内容图片及常规站点资源,总缓存大小为21MB,且内容几乎不会变更。我的Service Worker代码如下:

const all_assets = [...nnc, ...nc, ...checklist_content, ...info, ...fonts, ...other]

var cacheName = "ecl-cache-005"
self.addEventListener('install', function (event) {

    event.waitUntil((async () => {
        const cache = await caches.open(cacheName);
        await cache.addAll(all_assets);
    })());
});

self.addEventListener('activate', (e) => {
  e.waitUntil(caches.keys().then((keyList) => {
    return Promise.all(keyList.map((key) => {
      if (key === cacheName) { return; }
      return caches.delete(key);
    }))
  }));
});

self.addEventListener('fetch', function (event) {
    event.respondWith(
        // Try the cache
        caches.match(event.request).then(function (response) {
            // return it if there is a response,or else fetch again
            return response || fetch(event.request);
        })
    );
});

应用虽能正常运行,但install事件执行极慢,推测是由于Service Worker中需请求的URL数量庞大或19MB的图片资源导致,或两者皆有。请问是否有更优的离线实现方案?能否在install事件完成后单独缓存图片资源?我曾调研过Firestore和IndexedDB方案,但认为它们不兼容图片内容。


优化方案

1. 拆分缓存:install后单独缓存图片

完全可以在install事件完成后再缓存图片,这样能让Service Worker快速完成安装激活,不阻塞核心功能可用。具体思路:

  • 将资源拆分为核心资源(HTML、字体、基础脚本等,是页面运行必需的)和非核心资源(图片)
  • install阶段只缓存核心资源,确保快速完成安装流程
  • 在activate事件中启动图片的后台缓存,不影响用户使用

修改后的示例代码:

const core_assets = [...nnc, ...nc, ...checklist_content, ...info, ...fonts]
const image_assets = [...other] // 假设此处为所有图片资源集合
const cacheName = "ecl-cache-005"
const imageCacheName = "ecl-images-001"

self.addEventListener('install', function (event) {
    event.waitUntil((async () => {
        const cache = await caches.open(cacheName);
        await cache.addAll(core_assets);
        // 跳过等待,提前激活Service Worker
        self.skipWaiting();
    })());
});

self.addEventListener('activate', (e) => {
    e.waitUntil((async () => {
        // 激活后立即接管所有客户端页面
        await self.clients.claim();
        // 分批次缓存图片,避免单次发起过多请求阻塞浏览器
        const imageCache = await caches.open(imageCacheName);
        const batchSize = 50;
        for (let i = 0; i < image_assets.length; i += batchSize) {
            const batch = image_assets.slice(i, i + batchSize);
            await imageCache.addAll(batch);
        }
        // 清理旧缓存
        const keyList = await caches.keys();
        await Promise.all(keyList.map((key) => {
            if (key !== cacheName && key !== imageCacheName) {
                return caches.delete(key);
            }
        }));
    })());
});

self.addEventListener('fetch', function (event) {
    event.respondWith(
        caches.match(event.request).then(function (response) {
            // 先查核心资源缓存,再查图片缓存
            if (response) return response;
            return caches.open(imageCacheName).then(cache => {
                return cache.match(event.request) || fetch(event.request);
            });
        })
    );
});

2. 其他辅助优化措施

  • 分批次缓存核心资源:即使是核心资源,也可以分批次调用cache.addAll(),避免单次发起几百个请求导致浏览器请求队列阻塞
  • 资源压缩:对PNG图片进行无损压缩,减少总体积,加快下载速度
  • 优先缓存高频资源:如果部分HTML或图片是用户高频访问的,可以优先缓存这部分,剩余资源在后台逐步缓存
  • 去重资源列表:检查all_assets数组,确保没有重复URL,减少不必要的请求

关于IndexedDB的补充:其实IndexedDB支持存储图片Blob,但对于静态资源来说,Cache Storage本身就是更适配的方案,拆分缓存完全可以解决你的问题,不需要额外引入IndexedDB。


内容的提问来源于stack exchange,提问作者Sayed Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:21:32