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

Create React App中Web Workers致Jest报错:Cannot use 'import.meta' outside a module

解决方案:无需Eject即可在Create React App中使用Web Workers且兼容Jest

问题背景

在Create React App项目中使用如下代码创建Web Worker时:

const workerSimplerExample: Worker = useMemo(
    () => new Worker(new URL("../workers/simple-example.ts", import.meta.url), {type:"module"}),
    []
);

开发和生产构建均正常,但执行npm test或yarn test时,Jest会抛出错误:SyntaxError: Cannot use 'import.meta' outside a module,且不想通过eject修改Jest/Babel配置。


方案1:Mock Worker与import.meta.url(推荐)

在测试环境中替换Worker的实现,并Mock import.meta.url,避免触发不支持的语法。

  1. 在项目的src/setupTests.ts文件中添加以下代码:
// 模拟Web Worker类
class MockWorker {
  constructor(_url: string, _options?: any) {
    this.postMessage = jest.fn();
    this.onmessage = null;
    this.onerror = null;
  }
  postMessage: jest.Mock;
  onmessage: ((e: MessageEvent) => void) | null;
  onerror: ((e: ErrorEvent) => void) | null;
  terminate = jest.fn();
}

// Mock import.meta.url
Object.defineProperty(import.meta, 'url', {
  value: 'http://localhost:3000',
});

// 全局替换Worker
global.Worker = MockWorker as unknown as typeof Worker;
  1. 重新执行测试命令,此时Jest会使用Mock的Worker,不再触发import.meta相关错误。

方案2:环境区分,测试环境返回Mock Worker

在组件中直接判断环境,测试环境下不创建真实Worker,避免执行含import.meta的代码:

// 定义Mock Worker类型
type MockWorker = {
  postMessage: jest.Mock;
  onmessage: ((e: MessageEvent) => void) | null;
  onerror: ((e: ErrorEvent) => void) | null;
  terminate: jest.Mock;
};

const workerSimplerExample: Worker | MockWorker = useMemo(() => {
  if (process.env.NODE_ENV === 'test') {
    // 测试环境返回Mock实例
    return {
      postMessage: jest.fn(),
      onmessage: null,
      onerror: null,
      terminate: jest.fn(),
    };
  }
  // 生产/开发环境创建真实Worker
  return new Worker(new URL("../workers/simple-example.ts", import.meta.url), {type:"module"});
}, []);

该方案无需额外配置文件,直接在组件内处理环境分支。


方案3:将Worker文件放入Public目录,避免使用import.meta.url

把Worker文件编译后放到Public目录,直接通过静态路径访问,彻底避开import.meta:

  1. 在package.json中添加编译Worker的脚本:
"scripts": {
  "build-worker": "tsc src/workers/simple-example.ts --outDir public/workers --target ESNext --module ESNext",
  "prestart": "npm run build-worker",
  "prebuild": "npm run build-worker"
}
  1. 修改组件中创建Worker的代码:
const workerSimplerExample: Worker = useMemo(
    () => new Worker('/workers/simple-example.js', {type:"module"}),
    []
);
  1. 执行npm start或npm run build时,会自动先编译Worker文件到Public目录,测试时因代码未使用import.meta,不会触发Jest错误。

内容的提问来源于stack exchange,提问作者Tyler V.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 02:45:22