web workers 是解决预加载与预解析不阻塞主线程的核心手段,支持 dns 预解析、tcp 预连接及静态资源批量预加载,且规避了传统方式限制与执行风险。

Web Workers 是解决预加载与预解析任务不阻塞主线程的核心手段。它让资源获取、DNS 预解析、甚至轻量级 HTML 解析等操作在后台线程中完成,既避免干扰用户交互,又绕开了浏览器对 <link rel="prefetch"> 或 <link rel="preload"> 的策略限制(比如 Safari 不支持 prefetch、某些资源类型无法 onload 监听)。
为什么用 Web Worker 做预加载
传统方式如 new Image().src 只能加载图片;<link rel="stylesheet" disabled> 在 Firefox 中不可靠;<script type="text/cache"></script> 被多数现代浏览器忽略。而 Web Worker 不执行 DOM 操作、不触发渲染、不运行脚本,只做纯粹的 fetch 请求或 DNS 查询,天然满足“下载但不解析、不执行”的预加载需求。
实现 DNS 预解析 + TCP 预连接
Worker 本身不能直接调用 dns-prefetch 或 preconnect,但可通过 fetch() 触发底层连接建立。只要发起一次空请求(HEAD 或 GET),浏览器就会完成 DNS 解析、TCP 握手,甚至 TLS 协商(对 HTTPS 域名)。后续同域名请求可复用连接。
- 在 worker.js 中写:
fetch('https://api.example.com/', { method: 'HEAD', cache: 'no-store' }) - 避免实际下载响应体,节省带宽
- 多个域名可并行发起,不占用主线程事件循环
静态资源批量预加载
适合图片、字体、CSS、JS 等已知路径的资源。Worker 中使用 Promise.allSettled() 控制并发,并统一返回结果状态。
- 主线程传入 URL 列表:
worker.postMessage(['/assets/logo.png', '/css/app.css', '/js/utils.js']) - Worker 内逐个 fetch,不 await,避免阻塞其他请求
- 成功时缓存 blob 或仅确认 HTTP 200,失败时记录日志供调试
- 无需插入 DOM,也不影响当前页面资源优先级
安全与兼容性注意点
Web Worker 预加载不是万能方案,需规避常见陷阱:
- 跨域资源必须开启 CORS,否则 fetch 会失败(即使只是预加载)
- 不要在 Worker 中调用
importScripts()加载远程脚本——这会执行代码,违背“不解析”原则 - 移动端需留意 Worker 启动开销,建议在页面空闲期(如 scroll 结束后 500ms)再 postMessage 启动
- 对 HTML 页面预加载要谨慎:fetch 得到 HTML 后别尝试
DOMParser解析,否则可能触发脚本执行或样式计算











