close
  • 简体中文
  • Web Workers

    本文将介绍在 Rslib 项目中如何配置和使用 Web Workers

    Note

    使用 Web Workers 时,仅支持生成 ESM 格式的产物,因此 format 必须设置为 'esm'(默认值)。

    使用 Worker 构造器

    基本用法

    你可以使用标准构造器语法创建 Worker:

    index.ts
    new Worker(new URL('./worker.ts', import.meta.url));

    Rslib 会重写 Worker URL,使其指向生成的 JavaScript 文件,并将 Worker 输出为 ES 模块:

    index.js
    new Worker(new URL('./worker.js', import.meta.url), {
      type: 'module',
    });

    更多 Worker 语法可以查看 Rspack - Web Workers

    限制

    Rslib 依赖静态分析处理 new Worker 及类似的 Worker API,因此必须直接传入 new URL('./worker.ts', import.meta.url)。URL 字符串和通过变量传入的 URL 对象均不受支持:

    new Worker('./worker.ts');
    
    const workerUrl = new URL('./worker.ts', import.meta.url);
    new Worker(workerUrl);

    产物模式

    lib.bundle 配置项会影响 Worker 的构建方式。下面以同一组源码为例,展示 bundle 和 bundleless 模式分别生成的产物:

    src/index.ts
    src/worker.ts
    src/helper.ts
    export const worker = new Worker(new URL('./worker.ts', import.meta.url));

    Bundle 模式

    在 bundle 模式下,Rslib 会将 Worker 入口拆分为独立 chunk,并将 Worker 导入的模块打包到该 chunk 中:

    dist/index.js
    dist/worker.js
    const worker = new Worker(new URL('./worker.js', import.meta.url), {
      type: 'module',
    });
    export { worker };

    Bundleless 模式

    在 bundleless 模式下,Rslib 会保留源码的模块结构,并将 Worker URL 和 Worker 内部的导入重写为对应的 ESM 产物路径:

    dist/index.js
    dist/worker.js
    dist/helper.js
    const worker = new Worker(new URL('./worker.js', import.meta.url), {
      type: 'module',
    });
    export { worker };

    使用 query 后缀导入

    Rslib 支持在 bundle 模式下通过 query 后缀导入 Web Worker,详情请参考 Rsbuild - Web Workers

    输出独立 Worker 文件

    你可以在导入请求后添加 ?worker 来导入 Web Worker 脚本,Rslib 会为该 Worker 脚本生成独立的 ESM 文件:

    index.ts
    import MyWorker from './worker.ts?worker';
    
    export const worker = new MyWorker();

    内联 Worker

    你可以在导入请求后添加 ?worker&inline 来导入 Web Worker 脚本,Rslib 会在导入该 Worker 的 JavaScript 文件中内联 Worker 代码,不再生成独立的 Worker 文件:

    index.ts
    import InlineWorker from './worker.ts?worker&inline';
    
    export const worker = new InlineWorker();

    类型声明

    当你在 TypeScript 代码中使用 query 后缀导入 Worker 时,TypeScript 可能会提示该模块缺少类型定义:

    TS2307: Cannot find module './worker.ts?worker' or its corresponding type declarations.

    此时你可以在 tsconfig.json 中添加 @rslib/core 提供的 预设类型

    tsconfig.json
    {
      "compilerOptions": {
        "types": ["@rslib/core/types"]
      }
    }

    预设类型中已包含 *?worker*?worker&inline*?inline&worker 的类型声明。