Web Worker 不能直接做静态资源版本校验,因其无法访问 fetch、localStorage、caches 或 DOM;校验与更新必须由主线程发起,Worker 仅负责哈希比对等纯计算任务。

不能直接用 Web Worker 做静态资源版本校验,因为 Worker 无法访问 fetch、localStorage、caches 或 DOM,也不能发起网络请求或读取 Service Worker 的缓存状态。真正的校验与更新必须由主线程发起,Worker 只能承担计算密集型子任务——比如哈希比对、清单解析、滑动窗口统计等。
主线程负责触发与协调
所有关键动作必须在主线程完成:
- 通过
fetch('/assets/manifest.json')获取远程指纹清单(含各资源 SHA-256 哈希) - 从
localStorage或IndexedDB读取上一版本地指纹记录 - 调用
caches.keys()和caches.match()检查 Cache Storage 中是否存在对应资源 - 注册 Service Worker 并监听
controllerchange、statechange等生命周期事件 - 在合适时机(如页面空闲时)将待比对的哈希数组发给 Worker 处理
Worker 负责哈希比对与批量分析
Worker 不做 I/O,只接收结构化数据并执行纯计算:
- 接收主线程传来的两个哈希数组:本地旧清单 + 远程新清单
- 逐项比对,生成差异列表(如
[{url: "main.js", changed: true}]) - 对大量资源(如 500+ 条)启用分块处理,避免单次运行超 10ms
- 使用
postMessage(data, [data.buffer])零拷贝传输大数组(如二进制资源哈希切片) - 返回轻量结果,例如
{ updated: ["main.js"], unchanged: ["logo.png"] }
更新动作仍由主线程执行
Worker 输出差异后,主线程决定如何响应:
立即学习“前端免费学习笔记(深入)”;
- 对
changed === true的 JS/CSS 文件,用importScripts()动态加载新版本并触发重渲染 - 对图片等二进制资源,调用
caches.open('v2').then(cache => cache.put(url, response)) - 若检测到关键资源变更,向用户提示“有新版本”,并提供手动刷新按钮
- 调用
navigator.serviceWorker.getRegistration().then(r => r.update())主动检查 SW 更新
避开常见陷阱
这些细节不处理好,校验就形同虚设:
- 不要在本地文件协议(
file://)下测试,Worker 脚本必须通过 HTTP/HTTPS 加载 - HTML 文件本身要禁用强缓存(
Cache-Control: no-cache),否则用户永远看不到新 manifest - Service Worker 脚本更新需字节级变化,且需显式调用
self.skipWaiting()才能跳过 waiting 状态 - CDN、反向代理、浏览器磁盘缓存都可能拦截 manifest 请求,务必验证 Network 面板中该请求返回的是 200 + 实际变更内容



















