Web Workers 在 create-react-app 中:Jest 错误:无法在模块外部使用 ‘import.meta’。

huangapple go评论75阅读模式
英文:

Web Workers in create-react-app: Jest error: Cannot use 'import.meta' outside a module

问题

我使用 https://blog.logrocket.com/web-workers-react-typescript/ 来在使用 create-react-app 创建的应用程序中构建一些简单的 Web Workers。在其中,我有如下的代码:

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

这会生成一个URL,无论我是在开发模式下还是在生产模式下使用build目录,都可以正常工作。然而,无论我做什么,当我运行create-react-app的基本npm testyarn test时,Jest都会抛出错误,错误信息是:SyntaxError: Cannot use 'import.meta' outside a module

我找到的任何解决方案(其中没有很多,也没有一个很有把握的),都涉及到更改Jest或Babel的设置,而这在不弹出 create-react-app 的情况下是不允许的。

是否有人找到了在React中使用Web Workers的方法,而不会破坏Jest或弹出create-react-app?

英文:

I used https://blog.logrocket.com/web-workers-react-typescript/ to build some simple Web Workers in an application created with create-react-app. In it, I have code like this:

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

This generates a URL which works whether I'm in dev mode, or using the build directory in Production mode. However, no matter what I do, Jest throws errors when I run create-react-app's basic npm test or yarn test, with the error being: SyntaxError: Cannot use 'import.meta' outside a module

Any solutions I've found, (of which there aren't many, and none are very confident,) involve changing Jest or Bable settings in ways create-react-app doesn't allow unless I eject.

Has anyone figured out how to have Web Workers in React without breaking Jest or ejecting create-react-app?

答案1

得分: 0

为了解决这个问题,我发现可以将对 new URL() 的调用隔离出来,然后在 Jest 运行时替换加载的文件。感谢这个 GitHub 评论

首先,将 new URL() 隔离出来。我的文件位于 src/workers/simple-example-factory.ts

const getWorker = (): Worker => {
    return new Worker(new URL('./simple-example', import.meta.url));
}

export default getWorker;

然后,在 src/workers/simple-example-factory.fake.ts 中创建一个测试替身,并使用静态文件路径。

const getWorker = (): Worker => {
    return new Worker(new URL('./simple-example', ''));
}

export default getWorker;

然后,你可以在你的 JSX/TSX 文件中像这样获取工作实例:

import SimpleExampleFactory from "../workers/simple-example-factory";
...
const workerSimplerExample: Worker = SimpleExampleFactory();

此时,工作器应该在浏览器中仍然正常工作。 现在,为了修复 Jest,我们必须告诉它加载不同的文件。我们可以在使用 create-react-app 时通过 package.json 修改 Jest 配置(请参见文档)。

package.json

{
...
  "jest": {
    "moduleNameMapper": {
      "workers/(.*)-factory": "<rootDir>/src/workers/$1-factory.fake.ts"
    }
  },
...
}
英文:

To fix this, I figured out that I can isolate the call to new URL() and then replace the file which is loaded when Jest runs. Credit goes to this GitHub comment.

First, isolate new URL(). My file is located at src/workers/simple-example-factory.ts

const getWorker = (): Worker =&gt; {
    return new Worker(new URL(&#39;./simple-example&#39;, import.meta.url));
}

export default getWorker;

Then, create a test double at src/workers/simple-example-factory.fake.ts and use a static file path.

const getWorker = (): Worker =&gt; {
    return new Worker(new URL(&#39;./simple-example&#39;, &#39;&#39;));
}

export default getWorker;

Then, you can get an instance of the work in your JSX/TSX files like so:

import SimpleExampleFactory from &quot;../workers/simple-example-factory&quot;;
...
const workerSimplerExample: Worker = SimpleExampleFactory();

At this point, the worker should still work in the browser. Now, to fix Jest, we have to tell it to load a different file. We can modify the Jest configuration through package.json when using create-react-app (See documentation.)

package.json

{
...
  &quot;jest&quot;: {
    &quot;moduleNameMapper&quot;: {
      &quot;workers/(.*)-factory&quot;: &quot;&lt;rootDir&gt;/src/workers/$1-factory.fake.ts&quot;
    }
  },
...
}

huangapple
  • 本文由 发表于 2023年6月2日 07:24:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76386296.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定