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

如何仅从缓存加载Web Worker,避免蜂窝网络下载Stockfish引擎?

问题分析与解决方案

你现有代码里有个致命错误:SetCached里检测的URL是//www.linguashop.com/course/java/stockfish-16.1-single.js,但LoadEngine里加载的是//www.mysite.com/stockfish-16.1-single.js——两个完全不同的地址,检测的缓存和实际要加载的资源根本不沾边,这肯定会导致判断失效,实际触发下载。先把这个URL统一再说。

解决了URL问题后,还要注意:Web Worker的构造函数本身不支持直接指定cache-only这类缓存策略,它的请求遵循浏览器默认的HTTP缓存规则,哪怕你用HEAD请求确认过缓存存在,Worker加载时也可能因为缓存过期、浏览器缓存空间不足等原因重新发起网络请求。

下面给你两个可靠的方案:

方案一:通过Fetch+Blob创建Worker(推荐)

先使用fetch以only-if-cached模式获取引擎文件,确认从缓存拿到后,把资源转为Blob URL,再用这个URL创建Worker。这样能彻底确保资源来自缓存,不会触发网络下载:

let stockfish = null;

async function LoadEngine() {
  // 先判断网络类型
  if (navigator.connection?.type === 'cellular') {
    try {
      // 以only-if-cached模式获取资源
      const response = await fetch('//www.mysite.com/stockfish-16.1-single.js', {
        method: 'GET',
        cache: 'only-if-cached',
        mode: 'same-origin'
      });
      if (!response.ok) throw new Error('资源不在缓存中');
      // 转为Blob URL
      const blob = await response.blob();
      const blobUrl = URL.createObjectURL(blob);
      // 创建Worker
      stockfish = new Worker(blobUrl);
      // 用完记得释放Blob URL(可选,页面卸载时处理也行)
      stockfish.addEventListener('error', () => URL.revokeObjectURL(blobUrl));
      stockfish.addEventListener('message', () => {
        // 业务逻辑
      });
    } catch (err) {
      // 缓存中没有,蜂窝网络下不加载
      console.log('蜂窝网络下未缓存,不加载引擎');
      return;
    }
  } else {
    // WiFi/以太网下正常加载(可缓存)
    stockfish = new Worker('//www.mysite.com/stockfish-16.1-single.js');
  }
}

这个方案的核心是直接用缓存中的资源生成Worker的URL,完全绕开了Worker自身的请求逻辑,从根源上杜绝了网络下载。

方案二:用Service Worker拦截请求

如果你需要全局控制这类资源的加载,可以注册Service Worker,拦截所有Worker的请求,强制走缓存,禁止网络请求:

  1. 注册Service Worker(在主页面代码中):
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(reg => console.log('Service Worker注册成功'))
    .catch(err => console.log('Service Worker注册失败', err));
}
  1. 编写sw.js(Service Worker脚本):
self.addEventListener('fetch', (event) => {
  // 匹配Stockfish引擎的URL
  if (event.request.url.includes('stockfish-16.1-single.js')) {
    // 判断当前网络是否为蜂窝网络
    if (navigator.connection?.type === 'cellular') {
      // 仅从缓存获取,找不到就返回错误
      event.respondWith(caches.match(event.request));
    } else {
      // WiFi下正常缓存策略:先读缓存,再更新缓存
      event.respondWith(
        caches.match(event.request).then(cachedResponse => {
          const fetchPromise = fetch(event.request).then(networkResponse => {
            caches.open('stockfish-cache').then(cache => {
              cache.put(event.request, networkResponse.clone());
            });
            return networkResponse;
          });
          return cachedResponse || fetchPromise;
        })
      );
    }
  }
});

这个方案适合需要批量控制资源加载的场景,但需要处理Service Worker的注册、缓存更新等细节。

额外提示:navigator.connection.type在部分浏览器中可能有不同的取值(比如4g、3g也属于蜂窝网络),建议用navigator.connection.effectiveType做更精准的判断,比如effectiveType.startsWith('4g')或effectiveType.startsWith('3g')都视为蜂窝网络。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:19:55