zer*_*ewl 4 web-worker node.js typescript angular angular8
我尝试在Angular 8 Web Worker内导入节点模块,但出现编译错误“找不到模块”。有人知道如何解决吗?
我在的电子项目中使用创建了一个新工作人员ng generate web-worker app,如上述ng文档中所述。
一切正常,直到我添加一些导入,例如path或fs-extra:
/// <reference lib="webworker" />
import * as path from 'path';
addEventListener('message', ({ data }) => {
console.log(path.resolve('/'))
const response = `worker response to ${data}`;
postMessage(response);
});
Run Code Online (Sandbox Code Playgroud)
这种导入在任何其他ts组件中都可以正常工作,但是在Web Worker中,我收到此消息的编译错误,例如
Error: app/app.worker.ts:3:23 - error TS2307: Cannot find module 'path'.
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题?也许我需要在生成一些其他参数tsconfig.worker.json?
要重现该错误,请运行:
$ git clone https://github.com/hoefling/stackoverflow-57774039
$ cd stackoverflow-57774039
$ yarn build
Run Code Online (Sandbox Code Playgroud)
或在Travis上查看项目的构建日志。
注意:
1)我只发现这是一个类似的问题,但答案仅处理自定义模块。
2)我使用最小的电子种子测试了相同的导入,该种子使用web worker,并且可以正常工作,但是此示例使用了无角度的纯java脚本。
如您所见,第一个错误是TypeScript错误。看一下,tsconfig.worker.json我发现它设置types为一个空数组:
{
"compilerOptions": {
"types": [],
// ...
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
指定types将关闭包的自动包含@types。在这种情况下,这是一个问题,因为在中path有其类型定义@types/node。
因此,通过显式添加node到types数组来解决此问题:
{
"compilerOptions": {
"types": [
"node"
],
// ...
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
这解决了TypeScript错误,但是尝试再次构建时,我们遇到了一个非常类似的错误。这次直接从Webpack。
ERROR in ./src/app/app.worker.ts (./node_modules/worker-plugin/dist/loader.js!./src/app/app.worker.ts)
Module build failed (from ./node_modules/worker-plugin/dist/loader.js):
ModuleNotFoundError: Module not found: Error: Can't resolve 'path' in './src/app'
Run Code Online (Sandbox Code Playgroud)
为了弄清楚这一点,我们需要更深入地挖掘...
首先,重要的是要理解为什么导入path在所有其他模块中都起作用。Webpack具有目标(Web,节点等)的概念。Webpack使用此目标来确定要使用的默认选项和插件。
通常,使用Angular应用程序的目标@angular-devkit/build-angular:browser是web。但是,根据您的情况,postinstall:electron脚本实际上会进行修补node_modules以更改此内容:
postinstall.js (为简洁起见,省略了部分)
{
"compilerOptions": {
"types": [],
// ...
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
electron-rendererWebpack 对目标的处理类似于node。对我们来说特别有趣:NodeTargetPlugin默认情况下会添加。
您想知道该插件是做什么的吗?它将所有已知的Node.js内置模块添加为externals。在构建应用程序时,Webpack不会尝试捆绑外部组件。而是require在运行时使用解析它们。这就是使导入path工作的原因,即使它没有作为Webpack已知的模块安装也是如此。
使用单独编译工作程序WorkerPlugin。在他们的文档中,他们指出:
默认情况下,
WorkerPlugin捆绑工作程序代码时不运行任何已配置的Webpack插件-这样可以避免运行html-webpack-plugin twice。对于需要将插件应用于Worker代码的情况,请使用plugins选项。
查看WorkerPlugin深入内部的用法,@angular-devkit我们将看到以下内容:
@angular-devkit/src/angular-cli-files/models/webpack-configs/worker.js (简体)
{
"compilerOptions": {
"types": [
"node"
],
// ...
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
如我们所见,它使用该plugins选项,但仅用于负责TypeScript编译的单个插件。这样,由Webpack配置的默认插件(包括NodeTargetPlugin迷路的插件)就不会丢失,并且不会用于工作程序。
要解决此问题,我们必须修改Webpack配置。为此,我们将使用@angular-builders/custom-webpack。继续安装该软件包。
接下来,打开angular.json并更新projects > angular-electron > architect > build:
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./extra-webpack.config.js"
}
// existing options
}
}
Run Code Online (Sandbox Code Playgroud)
对重复相同的操作serve。
现在,extra-webpack.config.js在与以下目录相同的目录中创建angular.json:
ERROR in ./src/app/app.worker.ts (./node_modules/worker-plugin/dist/loader.js!./src/app/app.worker.ts)
Module build failed (from ./node_modules/worker-plugin/dist/loader.js):
ModuleNotFoundError: Module not found: Error: Can't resolve 'path' in './src/app'
Run Code Online (Sandbox Code Playgroud)
该文件导出将由@angular-builders/custom-webpack现有Webpack配置对象调用的函数。然后,我们可以搜索的所有plugins实例,WorkerPlugin并添加来修补其选项NodeTargetPlugin。