create-react-app 在Web Worker中动态导入时出现重复路径段错误(react-scripts 5,webpack 5)

zqry0prt  于 5个月前  发布在  React
关注(0)|答案(8)|浏览(64)

描述bug

当我的应用尝试通过Web Worker动态导入某些内容时,请求的路径中static/js部分被重复,导致404错误。
我可以在干净安装create-react-app的typescript模板的情况下重现这个问题。
需要满足的两个主要因素是:

  1. 一个web worker(我正在使用webpack 5的语法和import.meta.url)。
  2. package.json中设置一个homepage属性。如果应用程序直接通过localhost提供服务,似乎错误的解析部分不会发生。我们的生产环境使用子域名,所以我需要homepage属性。

你是否尝试恢复依赖项?

我在干净的安装中重现了这个问题。依赖项不是问题所在。
我使用的是yarn 1.22.18。我相信使用npm也会出现同样的问题。

$ yarn --version
1.22.18

你在用户指南中搜索了哪些术语?

  • webpack 5
  • web worker

环境

Environment Info:

  current version of create-react-app: 5.0.1
  running from C:\Users\<my-user-name>\AppData\Local\Yarn\Data\global\node_modules\create-react-app

  System:
    OS: Windows 10 10.0.19041
    CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz    
  Binaries:
    Node: 14.19.0 - C:\Program Files\nodejs\node.EXE        
    Yarn: 1.22.18 - C:\Program Files\nodejs\yarn.CMD        
    npm: 6.14.16 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: Not Found
    Edge: Spartan (44.19041.1266.0), Chromium (99.0.1150.52)
    Internet Explorer: 11.0.19041.1202
  npmPackages:
    react: ^18.1.0 => 18.1.0 
    react-dom: ^18.1.0 => 18.1.0 
    react-scripts: 5.0.1 => 5.0.1 
  npmGlobalPackages:
    create-react-app: Not Found

重现问题的步骤

  1. 将Web Worker添加到你的项目中,如in the webpack 5 docs所述。
  2. 在Web Worker内部,使用动态import()语句从其他地方加载内容。它可以是本地模块或来自node_modules的内容。
  3. 在某个地方消费web worker。
  4. 你还需要在package.json中设置homepage属性才能重现这个问题。(我在可复现演示部分有更详细的信息。)

预期行为

动态导入应该有效。

实际行为

动态导入失败,出现404错误。显示网络错误。路径包括static/js/static/js,而应该是static/js

可复现演示

  1. 使用“create react app”和TypeScript模板创建一个新应用:
    yarn create react-app example-app --template typescript
  2. 编辑package.json文件,添加以下两行代码:
"type": "module",
"homepage": ".",
  1. 添加一个名为src/OtherModule.ts的新文件,并添加以下内容:
export const message = "Message from another module.";
  1. src/App.tsx语句之前添加以下代码:
useEffect(() => {
    const worker = new Worker(new URL("./TestWorker.worker.ts", import.meta.url));
    worker.onmessage = (event: MessageEvent<any>) => {
        console.log(`[App] Received:`, event.data);
    };
    // The expected behaviour is for the worker to send a message in response to this one.
    // In reality, there's an error loading one of the chunks.
    worker.postMessage("abc");
  });
  1. src/App.tsx中的从build导入的static/js/static/js中添加:
import React, { useEffect } from 'react';
  1. 构建应用程序:
    static/js
  2. 通过网络服务器提供x2m25n1x文件夹。
  3. 访问网站并打开控制台。

预期行为:

控制台应显示App和Worker之间互相接收消息的日志输出。
x2m26n1x

实际行为:

显示网络错误。路径包括x2m27n1x,而应该是x2m28n1x。

bqjvbblv

bqjvbblv1#

我遇到了相同的问题。
我正在使用node v16.13.2和npm 8.1.2。
我尝试在react脚本的webpack配置中四处寻找,但没有成功。我现在打算创建一个脚本,将所有的static/js文件复制粘贴到static/js/static/js,作为目前的解决方法。

gkn4icbw

gkn4icbw2#

对我来说也是同样的问题。我只是创建了路径,以便现在可以工作。我正在使用的是:

  • 节点@16.15.1
  • React-scripts@5.0.1
  • React@18.2.0
ryoqjall

ryoqjall3#

我也在短期内实施了一个解决方法。我能够安全地确定哪些文件需要移动到static/js/static/js,而不是复制所有内容。
就我的情况而言,只有main.[hash].jsweb-worker.[hash].chunk.js仍然留在原始位置。
我将后者命名为:

new Worker(
    /* webpackChunkName: "web-worker" */
    new URL("./my-file-path.worker.ts", import.meta.url)
);

解除封锁是好事,但我还是希望看到这个问题得到修复,这样我就可以取消我的解决方法了。

kse8i1jr

kse8i1jr4#

我们也遇到了这个问题。移除$x^{homepage: '.'}$可能对我们来说不是一个选项。@JacobCutshall和@kenlyon,请你们能向我解释一下你们的解决方法吗?

noj0wjuj

noj0wjuj5#

我们也遇到了这个问题。移除homepage: '.'可能对我们来说不是一个选项。@JacobCutshall和@kenlyon,请你们能向我解释一下你们的解决方法吗?🙏
@kialam 我在我的构建过程中添加了一个函数:

import fse from "fs-extra"; // You could also use node's own "fe" module for moving files.
import path from "path";
import { fileURLToPath, URL } from "url";

async function handleWebpackPathBug() {
    const repoRootUrl = new URL("..", import.meta.url);
    const repoRoot = fileURLToPath(repoRootUrl);
    const sourceFolder = path.join(repoRoot, "build/static/js");
    const destinationFolder = path.join(sourceFolder, "static/js");

    if (!fse.existsSync(sourceFolder)) {
        throw new Error(
            `Failed to handle webpack path bug. Source folder (${sourceFolder}) does not exist.`
        );
    }

    await fse.ensureDir(destinationFolder);
    const staticJsFiles = await fse.readdir(sourceFolder);

    // Move all .js files that do not start with "main." or "web-worker." as those two get correctly loaded directly from static/js.
    const filesToMove = staticJsFiles.filter((val) => /^(?!main\.|web-worker\.).+\.js$/.test(val));

    for (const file of filesToMove) {
        await fse.move(path.join(sourceFolder, file), path.join(destinationFolder, file), {
            overwrite: true,
        });
    }
}
idfiyjo8

idfiyjo86#

可以通过在webpack中设置publicPath='auto'来解决这个问题,但是目前CRA还不支持这个设置。

b1uwtaje

b1uwtaje7#

@amcgee 你知道过去一年里CRA是否已经支持了publicPath='auto'吗?
今天我又遇到了这个bug,因为我的解决方法移动了一些本应该留在原始static/js位置的新数据块。

ccgok5k5

ccgok5k58#

对于任何遇到同样问题的人,我在craco.config.js上使用CRACO和以下配置解决了这个问题:

module.exports = {
  webpack: {
    configure: {
      output: {
        publicPath: 'auto',
      },
    },
  },
};

现在是2024年,但仍然不被CRA支持。

相关问题