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

React18/CRA部署后Web Worker导入失败,路径重复问题求助

解决Create React App中Web Worker部署后路径重复(static/js/static/js)的问题

问题背景

在create-react-app项目中使用Web Worker加密大文件,开发环境运行正常,但部署后出现MIME类型错误,排查发现new URL('../WebWorkers/encryption.worker.js', import.meta.url)生成的URL包含重复的static/js路径,导致加载失败。

Worker代码:

import * as CryptoJS from "crypto-js";

// eslint-disable-next-line no-restricted-globals
self.onmessage = async function (e) {
    const workerResult = await encryptFile(e.data.file, e.data.key);
    self.postMessage({result: workerResult, keyName: e.data.keyName}); // eslint-disable-line no-restricted-globals
};

// 你的encryptFile实现逻辑...

组件中初始化Worker的代码:

const webworker = React.useMemo(() => new Worker(new URL('../WebWorkers/encryption.worker.js', import.meta.url)), []);

报错信息:

Refused to execute script from 'https://DOMAIN+OF+THE+APP/publisher/static/js/static/js/541.fda53aa0.chunk.js' because its MIME type ('text/html') is not executable.


解决方案

方法1:使用Create React App内置的Web Worker支持(推荐)

Create React App从v4版本开始原生支持Web Worker的ES模块导入,无需手动处理URL路径:

  1. 修改组件中的Worker初始化代码:
// 直接导入worker文件,Webpack会自动处理打包和路径
import EncryptionWorker from '../WebWorkers/encryption.worker.js';

const webworker = React.useMemo(() => new EncryptionWorker(), []);
  1. 保持encryption.worker.js代码不变(可继续使用import * as CryptoJS from "crypto-js")。

这种方式下,Webpack会正确识别Worker文件,生产构建时将其打包到正确的static/js路径,不会出现重复拼接问题。

方法2:将Worker文件移至public目录

如果不想依赖内置的Worker支持,可将Worker文件放到项目public目录下,避免Webpack路径解析错误:

  1. 把encryption.worker.js移动到项目根目录的public文件夹中。
  2. 修改Worker文件,改用importScripts引入CryptoJS(public目录下的文件不被Webpack转译,无法使用ES模块导入):
// public/encryption.worker.js
// 可下载CryptoJS压缩包到public目录,或使用CDN链接
importScripts('https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.min.js');

self.onmessage = async function (e) {
    const workerResult = await encryptFile(e.data.file, e.data.key);
    self.postMessage({result: workerResult, keyName: e.data.keyName});
};

async function encryptFile(file, key) {
    // 加密逻辑直接使用全局的CryptoJS对象
}
  1. 在React组件中初始化Worker:
// 使用process.env.PUBLIC_URL适配部署的子目录路径
const webworker = React.useMemo(() => new Worker(`${process.env.PUBLIC_URL}/encryption.worker.js`), []);

方法3:用Craco修改Webpack配置(进阶)

如果需要保留原有的new URL写法,可使用craco修改Webpack输出配置,避免路径重复:

  1. 安装Craco:
npm install @craco/craco --save-dev
  1. 在项目根目录创建craco.config.js:
module.exports = {
  webpack: {
    configure: (webpackConfig, { env }) => {
      if (env === 'production') {
        // 定位Web Worker的规则配置
        const workerRule = webpackConfig.module.rules.find(rule => 
          rule.oneOf?.some(r => r.type === 'webworker')
        );
        
        if (workerRule) {
          workerRule.oneOf.forEach(rule => {
            if (rule.type === 'webworker') {
              // 自定义Worker输出文件名格式,避免路径重复
              rule.generator = {
                filename: 'static/js/[name].[contenthash:8].worker.js'
              };
            }
          });
        }
      }
      return webpackConfig;
    }
  }
};
  1. 修改package.json中的脚本命令,替换react-scripts为craco:
"scripts": {
  "start": "craco start",
  "build": "craco build",
  "test": "craco test"
}
  1. 保持原有的Worker和组件代码不变,重新构建部署即可。

内容的提问来源于stack exchange,提问作者hpertaia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:15:41