英文:
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 test
或yarn 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 => {
return new Worker(new URL('./simple-example', 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 => {
return new Worker(new URL('./simple-example', ''));
}
export default getWorker;
Then, you can get an instance of the work in your JSX/TSX files like so:
import SimpleExampleFactory from "../workers/simple-example-factory";
...
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
{
...
"jest": {
"moduleNameMapper": {
"workers/(.*)-factory": "<rootDir>/src/workers/$1-factory.fake.ts"
}
},
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论