Mik*_*ike 5 webpack angular-cli angular nrwl-nx webpack-5
我正在使用 Angular 11 和 Webpack 5 开展一个新项目。我的工作基于 Manfred Steyer 的Module Federation Plugin Example repo,它使用 Angular CLI。我不知道如何从我的两个应用程序之间共享的本地 Angular 库共享单例服务。
我会尽力解释我的设置.. 真的很抱歉这会持续多久。
root
package.json
projects/
shell/
src/app/
app.module.ts
app.component.ts
webpack.config.ts <-- partial config
mfe1/
src/app/
app.module.ts
app.component.ts
webpack.config.ts <-- partial config
shared/
src/lib/
global.service.ts
package.json <-- package.json for lib
Run Code Online (Sandbox Code Playgroud)
两个 app.component.ts 文件是相同的
import {GlobalService} from 'shared';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(shared: SharedService) {}
}
Run Code Online (Sandbox Code Playgroud)
global.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class GlobalService {
constructor() {
console.log('constructed SharedService');
}
}
Run Code Online (Sandbox Code Playgroud)
shell/webpack.config.ts
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
output: {
publicPath: "http://localhost:5000/",
uniqueName: "shell"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
remotes: {
'mfe1': "mfe1@http://localhost:3000/remoteEntry.js"
},
shared: ["@angular/core", "@angular/common", "@angular/router"]
})
],
};
Run Code Online (Sandbox Code Playgroud)
mfe1/webpack.config.ts
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
output: {
publicPath: "http://localhost:3000/",
uniqueName: "mfe1"
},
optimization: {
// Only needed to bypass a temporary bug
runtimeChunk: false
},
plugins: [
new ModuleFederationPlugin({
// For remotes (please adjust)
name: "mfe1",
library: {type: "var", name: "mfe1"},
filename: "remoteEntry.js",
exposes: {
'./Module': './projects/mfe1/src/app/app.module.ts',
},
shared: ["@angular/core", "@angular/common", "@angular/router"]
})
],
};
Run Code Online (Sandbox Code Playgroud)
共享库 package.json
{
"name": "shared",
"version": "0.0.1",
"main": "src/public-api.ts",
"peerDependencies": {
"@angular/common": "^11.0.0-next.5",
"@angular/core": "^11.0.0-next.5"
},
"dependencies": {
"tslib": "^2.0.0"
}
}
Run Code Online (Sandbox Code Playgroud)
此配置编译并运行,但mfe1实例化一个新的GlobalService. 我看到“构建的 SharedService”记录在应用程序加载上,然后在加载远程模块后再次看到。我试图遵循ScriptedAlchemy 的另一个示例,但我不知道如何使其工作。它要么编译并运行并创建两个实例,要么无法编译引用丢失的模块,这取决于我确定我如何弄乱我的配置。
ScriptedAlchemy 示例使我似乎需要shared在webpack.config.ts文件中的库数组中引用我的共享库。这完全有道理,但我无法让它工作
shell/webpack.config.ts and mfe1/webpack.config.ts
...
shared: ["@angular/core", "@angular/common", "@angular/router", "shared"]
Run Code Online (Sandbox Code Playgroud)
如果我以这种方式引用本地库,则在构建过程中不可避免地会出现错误
Error: Module not found: Error: Can't resolve 'shared' in '/Path/to/module-federation-plugin-example/projects/shell/src/app'
Run Code Online (Sandbox Code Playgroud)
我发布的例子是简化的。希望不要过分,但这里有一个链接,指向一个显示问题的存储库
Mik*_*ike 10
TL; 博士
webpack.config.ts我会注意到我的项目是一个使用 Angular CLI 的 NX Monorepo。我正在使用(目前)Angular 11.0.0-next 和 Webpack 5,在撰写本文时,它仅可作为 ng11 的选择加入。
如果您在 tsconfig 中使用路径别名,您习惯于导入诸如“@common/my-lib”之类的本地库,但是您不能在 webpack 配置中通过别名共享模块。此外,如果您使用的是 NX,如果您从绝对或相对库路径导入,您的 linting 会抱怨,因此 Webpack 想要什么和 nx/tslint 想要什么之间存在脱节。
在我的项目中,我有一些库别名,如下所示
tsconfig.base.json
...
"paths": {
"@common/facades": [
"libs/common/facades/src/index.ts"
],
"@common/data-access": [
"libs/common/data-access/src/index.ts"
]
}
Run Code Online (Sandbox Code Playgroud)
为了在我的 webpack 配置中完成这项工作。我们必须使用这些别名,但是使用import选项告诉 webpack 在哪里可以找到这些库
apps/shell/webpack.config.js
...
plugins: [
new ModuleFederationPlugin({
remotes: {
'dashboard': 'dashboard@http://localhost:8010/remoteEntry.js',
'reputation': 'reputation@http://localhost:8020/remoteEntry.js'
},
shared: {
"@angular/core": {
"singleton": true
},
"@angular/common": {
"singleton": true
},
"@angular/router": {
"singleton": true
},
"@angular/material/icon": {
"singleton": true
},
"@common/data-access": {
"singleton": true,
"import": "libs/common/data-access/src/index"
},
"@common/facades": {
"singleton": true,
"import": "libs/common/facades/src/index"
},
"rxjs": {
"singleton": true
},
"ramda": {
"singleton": true
}
}
})
]
Run Code Online (Sandbox Code Playgroud)
That solved the issues I was having with Webpack being unable to find modules at compile time.
My second problem was that I was attempting to share common facades that depended on common data access services. I didn't think to share the data access services because they are stateless, but this caused my MFEs to instantiate new singletons. This must be because the shared services had 'unshared' dependencies. Sharing my data access layer along with my facade layer resulted in shared singletons throughout my app.
The issue of dependencies is the most important thing here, because it's harder to debug. There are no errors or anything -- things just don't work like you expect. You may not even realize that you have two instances of a shared service at first. So, if you run into this issue take a look at your dependencies and make sure you're sharing everything you need. This is probably an argument for keeping minimal shared state/dependencies across your apps.
| 归档时间: |
|
| 查看次数: |
4762 次 |
| 最近记录: |