1。打字稿错误
您已经注意到第一个错误是 TypeScript 错误。查看tsconfig.worker.json 我发现它将types 设置为一个空数组:
{
"compilerOptions": {
"types": [],
// ...
}
// ...
}
指定types 会关闭automatic inclusion of @types packages。在这种情况下这是一个问题,因为path 在@types/node 中有其类型定义。
所以让我们通过将node 显式添加到types 数组来解决这个问题:
{
"compilerOptions": {
"types": [
"node"
],
// ...
}
// ...
}
这修复了 TypeScript 错误,但是尝试再次构建时,我们会遇到非常相似的错误。这次直接来自 Webpack。
2。网页包错误
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'
要弄清楚这一点,我们需要深入挖掘......
为什么它在其他任何地方都有效
首先,重要的是要了解为什么导入 path 在所有其他模块中都有效。 Webpack 有targets(web、node 等)的概念。 Webpack 使用这个目标来决定使用哪些默认选项和插件。
通常使用@angular-devkit/build-angular:browser 的Angular 应用程序的目标是web。但是,在您的情况下,postinstall:electron 脚本实际上修补了node_modules 以改变它:
postinstall.js(为简洁起见省略部分内容)
const f_angular = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js';
fs.readFile(f_angular, 'utf8', function (err, data) {
var result = data.replace(/target: "electron-renderer",/g, '');
var result = result.replace(/target: "web",/g, '');
var result = result.replace(/return \{/g, 'return {target: "electron-renderer",');
fs.writeFile(f_angular, result, 'utf8');
});
目标electron-renderer 被Webpack 以与node 类似的方式处理。对我们来说特别有趣:它默认添加了NodeTargetPlugin。
你想知道那个插件是做什么的?它将所有已知的 Node.js 内置模块添加为 externals。在构建应用程序时,Webpack 不会尝试捆绑外部。相反,它们在运行时使用require 解决。这就是导入 path 的原因,即使它没有作为 Webpack 已知的模块安装。
为什么它对工人不起作用
worker 使用WorkerPlugin 单独编译。他们在documentation 中声明:
默认情况下,WorkerPlugin 在捆绑工作代码时不会运行您配置的任何 Webpack 插件 - 这可以避免运行像 html-webpack-plugin twice 这样的东西。对于需要将插件应用到 Worker 代码的情况,请使用 plugins 选项。
查看WorkerPlugin 在@angular-devkit 深处的用法,我们看到以下内容:
@angular-devkit/src/angular-cli-files/models/webpack-configs/worker.js(简体)
new WorkerPlugin({
globalObject: false,
plugins: [
getTypescriptWorkerPlugin(wco, workerTsConfigPath)
],
})
正如我们所见,它使用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
}
}
对serve重复同样的操作。
现在,在与angular.json 相同的目录中创建extra-webpack.config.js:
const WorkerPlugin = require('worker-plugin');
const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
module.exports = (config, options) => {
let workerPlugin = config.plugins.find(p => p instanceof WorkerPlugin);
if (workerPlugin) {
workerPlugin.options.plugins.push(new NodeTargetPlugin());
}
return config;
};
该文件导出一个函数,该函数将由 @angular-builders/custom-webpack 使用现有的 Webpack 配置对象调用。然后我们可以在所有plugins 中搜索WorkerPlugin 的实例并修补其选项添加NodeTargetPlugin。