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路径:
- 修改组件中的Worker初始化代码:
// 直接导入worker文件,Webpack会自动处理打包和路径 import EncryptionWorker from '../WebWorkers/encryption.worker.js'; const webworker = React.useMemo(() => new EncryptionWorker(), []);
- 保持
encryption.worker.js代码不变(可继续使用import * as CryptoJS from "crypto-js")。
这种方式下,Webpack会正确识别Worker文件,生产构建时将其打包到正确的static/js路径,不会出现重复拼接问题。
方法2:将Worker文件移至public目录
如果不想依赖内置的Worker支持,可将Worker文件放到项目public目录下,避免Webpack路径解析错误:
- 把
encryption.worker.js移动到项目根目录的public文件夹中。 - 修改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对象 }
- 在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输出配置,避免路径重复:
- 安装Craco:
npm install @craco/craco --save-dev
- 在项目根目录创建
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; } } };
- 修改
package.json中的脚本命令,替换react-scripts为craco:
"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" }
- 保持原有的Worker和组件代码不变,重新构建部署即可。
内容的提问来源于stack exchange,提问作者hpertaia
相关产品推荐
相关产品推荐

