如何使用ES模块Worker_HTML ES Module Worker实现HTML模块化开发?

2026-04-29 01:002阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计861个文字,预计阅读时间需要4分钟。

如何使用ES模块Worker_HTML ES Module Worker实现HTML模块化开发?

普通Worker默认运行在classic模式,无法解析import语句;只有显式声明type: 'module',浏览器才会按ES模块规范加载并解析依赖。在不加选项时,不要害怕worker.js里只有一行import { foo } from './utils.js';,也会直接报错SyntaxError: Cannot use import statement outside a module。

模块 Worker 自动启用顶层 await、动态 import() 和裸 specifier 支持(需配合 importMap),但代价是:它完全禁用 importScripts() —— 所有依赖必须走标准 import 链。

new Worker() 路径必须是同源可访问的 URL

模块 Worker 对路径更敏感,常见失败原因:

  • new Worker('data:text/javascript,import%20x%20from%20"./a.js"') → 不合法:DataURL 不支持模块解析,会报 Failed to construct 'Worker': Module scripts are not supported for data URLs
  • new Worker('./worker.js', { type: 'module' }) → 成功,但要求 worker.js 能被服务器以 Content-Type: application/javascript+module 或至少 application/javascript 返回
  • 开发时用 file:// 协议打开 HTML → 所有模块 Worker 加载失败(CORS + 协议限制),必须起本地服务(如 npx serve 或 Vite)

主线程与模块 Worker 之间不能共享函数或类实例

即使双方都用 ES 模块,postMessage() 仍走结构化克隆算法,以下内容会被忽略或报错:

立即学习“前端免费学习笔记(深入)”;

  • postMessage({ fn: () => {} }) → 函数丢失,收端得到 {}
  • postMessage(new Date()) → 变成字符串,不是 Date 实例
  • postMessage(arrayBuffer, [arrayBuffer]) → 可转移,但接收方必须用 e.data.buffer 重新构造视图,不能直接当原 ArrayBuffer 用

正确做法是只传纯数据(ObjectArrayNumberStringArrayBuffer 等可克隆类型),复杂逻辑封装成序列化/反序列化协议,比如用 JSON.stringify() + JSON.parse() 控制字段粒度。

模块 Worker 中不能用 localStoragedocumentwindow

这是所有 Worker 的共性,但模块 Worker 容易让人误以为“既然能 import,那是不是也能访问全局对象”——不能。模块 Worker 的全局对象是 self,它没有 localStoragedocumentwindowfetch(除非显式启用,且部分浏览器仍限制)、console(有,但输出在 DevTools 的 Workers 面板下)。

典型陷阱:

  • 在模块 Worker 里写 import { api } from './api.js',而 api.js 内部用了 localStorage.getItem() → 运行时报 ReferenceError: localStorage is not defined
  • 想用 fetch 加载模型权重?可以,但需确认目标域名允许跨域,且浏览器支持(Chrome ≥ 99、Firefox ≥ 91);否则改用主线程 fetch 后通过 postMessage(..., [arrayBuffer]) 传输二进制

真正容易被忽略的是:模块 Worker 的错误堆栈默认不包含源映射,若用构建工具(如 Vite、Webpack)打包,务必开启 build.sourcemap 并确保 worker.js 的 sourcemap 被正确加载,否则调试时只能看到压缩后的一行代码。

标签:html

本文共计861个文字,预计阅读时间需要4分钟。

如何使用ES模块Worker_HTML ES Module Worker实现HTML模块化开发?

普通Worker默认运行在classic模式,无法解析import语句;只有显式声明type: 'module',浏览器才会按ES模块规范加载并解析依赖。在不加选项时,不要害怕worker.js里只有一行import { foo } from './utils.js';,也会直接报错SyntaxError: Cannot use import statement outside a module。

模块 Worker 自动启用顶层 await、动态 import() 和裸 specifier 支持(需配合 importMap),但代价是:它完全禁用 importScripts() —— 所有依赖必须走标准 import 链。

new Worker() 路径必须是同源可访问的 URL

模块 Worker 对路径更敏感,常见失败原因:

  • new Worker('data:text/javascript,import%20x%20from%20"./a.js"') → 不合法:DataURL 不支持模块解析,会报 Failed to construct 'Worker': Module scripts are not supported for data URLs
  • new Worker('./worker.js', { type: 'module' }) → 成功,但要求 worker.js 能被服务器以 Content-Type: application/javascript+module 或至少 application/javascript 返回
  • 开发时用 file:// 协议打开 HTML → 所有模块 Worker 加载失败(CORS + 协议限制),必须起本地服务(如 npx serve 或 Vite)

主线程与模块 Worker 之间不能共享函数或类实例

即使双方都用 ES 模块,postMessage() 仍走结构化克隆算法,以下内容会被忽略或报错:

立即学习“前端免费学习笔记(深入)”;

  • postMessage({ fn: () => {} }) → 函数丢失,收端得到 {}
  • postMessage(new Date()) → 变成字符串,不是 Date 实例
  • postMessage(arrayBuffer, [arrayBuffer]) → 可转移,但接收方必须用 e.data.buffer 重新构造视图,不能直接当原 ArrayBuffer 用

正确做法是只传纯数据(ObjectArrayNumberStringArrayBuffer 等可克隆类型),复杂逻辑封装成序列化/反序列化协议,比如用 JSON.stringify() + JSON.parse() 控制字段粒度。

模块 Worker 中不能用 localStoragedocumentwindow

这是所有 Worker 的共性,但模块 Worker 容易让人误以为“既然能 import,那是不是也能访问全局对象”——不能。模块 Worker 的全局对象是 self,它没有 localStoragedocumentwindowfetch(除非显式启用,且部分浏览器仍限制)、console(有,但输出在 DevTools 的 Workers 面板下)。

典型陷阱:

  • 在模块 Worker 里写 import { api } from './api.js',而 api.js 内部用了 localStorage.getItem() → 运行时报 ReferenceError: localStorage is not defined
  • 想用 fetch 加载模型权重?可以,但需确认目标域名允许跨域,且浏览器支持(Chrome ≥ 99、Firefox ≥ 91);否则改用主线程 fetch 后通过 postMessage(..., [arrayBuffer]) 传输二进制

真正容易被忽略的是:模块 Worker 的错误堆栈默认不包含源映射,若用构建工具(如 Vite、Webpack)打包,务必开启 build.sourcemap 并确保 worker.js 的 sourcemap 被正确加载,否则调试时只能看到压缩后的一行代码。

标签:html