@angular-architects/模块编织
与Angular CLI无缝地使用Webpack模块联合会.
谢谢
我们站在巨人的肩上。 感谢以下帮助实现这个项目的人:
- 科勒姆·费里Nx 小组成员
- 扎克・杰克逊,模块联合会发明者
- 托比亚斯·克珀斯, Webpack 创建者
- 德米特里·谢克霍夫佐夫,角 GDE 数据
- 迈克尔·埃格-齐克斯,角建筑师
先决条件
- 角 CLI 12 或以上
动机
模块联合会允许将单独编译和部署的代码(如微前端或插件)加载到应用程序中. 这个插件使得模块联合会与Angular和CLI合作.
支持若干技术
• 支持网络包装和rspack(实验性,下源)
QQ 支持角 CLI 和 Nx
特征
* 生成模块联盟配置的骨架.
QQ 安装自定义构建器以启用模块联盟 .
* 指定一个新的港口服务(ng serve)几个项目同时进行.
模块 Federation 配置是一个 部分 网页包配置。 它只包含控制模块联合会的东西. 其余的由CLI照常产生.
自1.2版以来,我们还提供一些先进的功能,例如:
动态模块联合会支助
分享 Monorepo 的 Libs
要使用哪个版本 ?
我们将提供至少每个角力大修一个大修,以跟踪角力生态系统及其创新:
- 角12: @angular-architects/module-federation: ^12.0.0 (中文(简体) )
- 角13: @angular-architects/模块-federation:~14.2.0
- 角14: @angular-architects/module-federation: ^14.3.0
- 角15: @angular-architects/module-federation: ^15.0
- 角16: @angular-architects/module-federation: ^16.0
- 角17: @angular-architects/module-federation: ^17.0
- 角18: @angular-architects/module-federation: ^18.0
- 角19: @angular-architects/模块-发音:^19.0.0
- 角20: @angular-architects/模块-federation: ^20.0.0
- 角 21: @angular-architects/module-fedferation: ^21. 2.0
- 角22: @angular-architects/module-federation: ^22.0.0 (中文(简体) )
从Angular 13开始,我们不得不添加一些修改来适应Angular CLI. 请见下一节.
网络包装和红外包装
插件的ng-add图问您是否想要使用传统的基于Webpack的构建器,还是(目前实验性,快活性,下一代)的rspack构建器. 两者都通过模块联合会得到支持.
对于红外线整合,我们是在 @nx/angular-rspack ——最初是科勒姆·费里出色的社区项目(Colum Ferry)@ng-rsbuild/plugin-angular 编号 : @ng-rspack/build),现由Nx团队维护. 因此,所有使rspack与Angular合作的功劳都归于Colum和Nx团队.
寻找 Esbuild/ applicationBuilder 路线吗 ? 即土著联合会,它现在生活在自己的组织中: github.com/土生土长。 。 。 .
更新
此库支持 ng update数字 :
ng update @angular-architects/module-federation
如果用手更新(例如通过) npm install),确保您同时安装相应的版本 @angular-builders/custom-webpack 匹配您的 Angular 主干道(Angular 22 第22版,Angular 21 第21版等).
注:最多并包括Angular 21,该套件使用
ngx-build-plus以插入网络包配置。 至于Angular 22 它使用@angular-builders/custom-webpack运行ng update @angular-architects/module-federation自动迁移已有的工作空间;如果您手动更新,请删除ngx-build-plus切换你的angular.json建构器为@angular-builders/custom-webpack:*。 。 。 .
从角12或更低处升级
从Angular 13开始,CLI生成了EcmaScript模块而不是脚本文件. 这影响了我们如何与模块联合会合作.
有关移民的信息:
如果你从头开始, ng add 将照顾这些设置.
使用量 +++
角 CLI 函数
ng add @angular-architects/module-federation- 调整生成
webpack.config.js文件 - 重复此选项用于您工作空间中的更多工程( 如果需要)
无
npm install --save-dev @angular-architects/module-federationnx g @angular-architects/module-federation:init- 调整生成
webpack.config.js文件 - 重复此选项用于您工作空间中的更多工程( 如果需要)
QQ 第14版+: 使用 -- 类型切换来获得新的精简配置
有了第14版,我们引入了一个 -- 类型开关 ng add 编辑 init 示意图. 设定为以下一个值以获得更精简的配置文件 :
hostdynamic-hostremote
一个动态主机在运行时从配置文件读取微前端的URL.
开始QQ
请在这里找到一个 教程 显示如何使用此插件.

页:1
请看看这个 关于模块联合会的文章系列。 。 。 .
实例
这个 实例 将微前端装入外壳 :
请看看这个例子 读取我它指出使用模块联合会的重要方面.
高级特性
虽然上述教程和博客文章指导您使用模块联合会,但本节提醒您注意这个插件和模块联合会的一般一些高级方面.
动态模块联合会
自1.2版以来,我们提供了帮助器功能,使动态模块联合会变得非常容易. 用我们的 loadRemoteModule 函数而不是动态 include例如,加上懒惰路线:
import { loadRemoteModule } from '@angular-architects/module-federation';
[...]
const routes: Routes = [
[...]
{
path: 'flights',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:3000/remoteEntry.js',
exposedModule: './Module'
})
.then(m => m.FlightsModule)
},
[...]
]
如果可能的话,装入 remoteEntry 领先 这使得Module Federation在商谈共享库的版本时可以考虑远程元数据.
为此,你可以打电话 loadRemoteEntry 在拖住角前 :
// main.ts
import { loadRemoteEntry } from '@angular-architects/module-federation';
Promise.all([
loadRemoteEntry({
type: 'module',
remoteEntry: 'http://localhost:3000/remoteEntry.js',
}),
])
.catch((err) => console.error('Error loading remote entries', err))
.then(() => import('./bootstrap'))
.catch((err) => console.error(err));
这个 bootstrap.ts 文件包含通常在 main.ts 因此,它呼吁 platform.bootstrapModule(AppModule)。您真的需要将前置文件调用载荷 Remote Entry 和动态导入的组合起来,并装入另一个拖曳Angular 的文件,因为Angular本身在版本谈判期间已经是一个受尊重的共享库.
然后,在装入远程模块时,你会提到 remoteEntry 属性,因为它也作为远程的内部标识符:
import { loadRemoteModule } from '@angular-architects/module-federation';
[...]
const routes: Routes = [
[...]
{
path: 'flights',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:3000/remoteEntry.js',
exposedModule: './Module'
})
.then(m => m.FlightsModule)
},
[...]
]
分享 Monorepo 的 Libs
假设你有一个角CLI Monorepo 或 Nx Monorepo 使用路径映射 tsconfig.json 用于提供图书馆:
"shared-lib": [
"projects/shared-lib/src/public-api.ts",
],
您现在可以在您的单重播中共享您所有微前端的库( apps) 。 这意味着这个库只装入一次.
14+版本中新的精简配置
从第14版开始,我们使用一个更蒸汽的配置,当使用上面提到的 -- -- 类型开关时,有以下一个选项: remote, (中文(简体) ), host, (中文(简体) ), dynamic-host。 。 。 .
这个新配置会自动分享所有本地解放者. 因此,你不需要做任何事情.
然而,如果想要控制,可以使用本地图书馆共享哪些图书馆 sharedMappings 数组 :
module.exports = withModuleFederationPlugin({
shared: {
...shareAll({
singleton: true,
strictVersion: true,
requiredVersion: 'auto',
}),
},
sharedMappings: ['shared-lib'],
});
请不要忘记,分享模块联盟 总是一个选择: 您需要添加此设置到每个共享的微前端 .
遗产-语法和版本 12-13
在以前的版本中,您将 lib 名称与 SharedMappings 在您的网络包配置中的实例 :
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
[...]
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, '../../tsconfig.json'),
['auth-lib']
);
从1.2版本开始,使用锅炉板 SharedMappings 是为您生成的。 你只需要在这里加上你的lib的名字.
这个生成的代码包括提供这些库的元数据 ModuleFederationPlugin 并添加一个插件,确保即使是由Angular编译器生成的源代码也使用共享的库版本.
plugins: [
new ModuleFederationPlugin({
[...]
shared: {
[...]
...sharedMappings.getDescriptors()
}
}),
sharedMappings.getPlugin(),
],
共享帮助
帮助函数共享为共享依赖添加了一些附加选项 :
shared: share({
"@angular/common": {
singleton: true,
strictVersion: true,
requiredVersion: 'auto',
includeSecondaries: true
},
[...]
})
新增选项是: requireVersion: 'auto' 财务报告和审定财务报表 includeSecondaries。 。 。 .
需要Version: “自动”
如果你准备好了 requireVersion 改为 'auto',帮助者选择您定义的版本 package.json。 。 。 .
这有助于解决没有(完全)满足同行依赖和次级切入点的问题(见下文的坑部分).
默认,它需要 package.json 最接近呼叫者(通常为: webpack.config.js) (中文(简体) ). 不过,你可以把路传给别人 package.json 使用第二个可选参数。 您还需要在您所在的节点依赖中定义共享的 libray package.json。 。 。 .
您可以跳过此选项并调用 setInferVersion(true) 在此之前:
setInferVersion(true);
包括二级
如果设置为 true,所有二级切入点也都加入。 就 @angular/common 这也是 @angular/common/http, (中文(简体) ), @angular/common/http/testing, (中文(简体) ), @angular/common/testing, (中文(简体) ), @angular/common/http/upgrade,以及 @angular/common/locales。这一详尽清单表明,使用这一选项是为了 @angular/common 这不是个好主意 因为通常你不需要他们.
自第14.3版以来,
includeSecondaries默认为真实.
然而,这个选项可以帮助快速实验,或者如果你想快速共享一个像 @angular/material 有很多次要的切入点.
即使你分享太多,模块联盟只会在运行时装入需要的. 然而,请记住,共享的包不能被树震动.
要跳过一些次要切入点,您可以指定一个配置选项,而不是 true数字 :
shared: share({
"@angular/common": {
singleton: true,
strictVersion: true,
requiredVersion: 'auto',
includeSecondaries: {
skip: ['@angular/common/http/testing']
}
},
[...]
})
全部共享
这个 shareAll 帮助者共享您定义的所有依赖关系 package.json编辑 package.json 如上所述:
shared: {
...shareAll({
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
}),
...sharedMappings.getDescriptors()
}
用于共享的选项 package.json。 。 。 .
这在单回波场景中可能有用,在做一些实验/麻烦射击时也会有用.
耳机和平板电脑
谢谢 迈克尔·埃格-齐克斯,谁想出了这些解决方案.
Module Federation允许将共享的依赖直接捆绑入您的应用程序捆绑. 因此,你不需要加载额外的捆绑每个共享依赖。 当存在许多共享的依赖性时,这可能会对提高应用程序的启动性能产生兴趣.
改进启动时间的一种可能用途是设定 eager 改为 true 刚刚 为宿主. 以后装入的遥控器可以重新使用这些急切的依赖性,尽管它们已经通过宿主的捆绑(如: main.js) (中文(简体) ). 这最有效,如果主机总是拥有最高的兼容版本共享依赖. 还有,在这种情况下,你不需要在前面装入远程入口.
虽然 eager 旗帜是模块联邦自其诞生之初就提供的框外特性,我们需要调整Angular CLI使用的网页包配置一点来避免生成捆绑中的代码重复. 新的 withModuleFederationPlugin 用此插件的 第 14 版引入的助手默认这样做 。 配置只是需要设置 渴望 true。 。 。 .
module.exports = withModuleFederationPlugin({
shared: {
...shareAll({
singleton: true,
eager: true,
pinned: true,
strictVersion: true,
requiredVersion: 'auto',
}),
},
});
如上一个例子所示,我们还增加了另一个财产:被钉住。 这样可以确定,共享的依赖性被放入应用程序的(例如主机的)捆绑中,尽管没有在那里使用. 这可以预先装入以后需要但随后通过一捆装入的微前端的依赖性.
Nx 整合
如果插件检测到您正在使用 Nx( 它基本上寻找一个) nx.json),它使用由Nx提供的构建器.
Angular Universal (服务员侧面渲染)
自此插件的12.4.0版本起,我们支持新的 日记-基于服务器侧面渲染(SSR)的Angular Universal API. 请注意安全部门改革 仅限 在特定情况下是有意义的,例如,针对需要SEO的客户软件.
为了利用安保部门改革,应使安保部门改革能够 全部 您的联邦项目(例如外壳和微前端).
在添加模块联合会之前添加角通用
如果您从新项目开始, 在添加模块联合会之前, 应当添加 Angular Universal:
ng add @nguniversal/common --project yourProject
ng add @angular-architects/module-federation --project yourProject
然后,调整生成的端口 server.ts数字 :
const PORT = 5000;
在此之后,您可以编译和运行您的应用程序 :
ng build yourProject && ng run yourProject:server
node dist/yourProject/server/main.js
在现有模块联合会项目中增加角通用
如果您已经使用 @angular-architects/module-federation,可以这样添加Angular Universal:
-
更新
@angular-architects/module-federation改为最新版本(qq 12.4).npm i @angular-architects/module-federation@latest -
现在,我们需要暂时禁用同步的靴子。 虽然模组联合会需要它,但由Angular Universal提供的示意图假设Angular被以传统(同步)方式被拖出. 在使用这些Schematics后,我们必须再次启用同步的靴子夹:
ng g @angular-architects/module-federation:boot-async false --project yourProject ng add @nguniversal/common --project yourProject ng g @angular-architects/module-federation:boot-async true --project yourProject -
模组联合会和Angular Universal这两个组织现在都到位了,我们可以将它们相互结合:
ng g @angular-architects/module-federation:nguniversal --project yourProject -
在生成时调整已使用的端口
server.ts文件 :const PORT = 5000; -
现在,您可以编译和运行您的应用程序 :
ng build yourProject && ng run yourProject:server node dist/yourProject/server/main.js
示例
请找到一个 实例 在树枝里 ssr。 。 。 .
试试看
试试看,你可以去检查一下 main 我们的分支 实例。在安装依赖之后(npm i),您可以重复将Angular Universal添加到以上两次描述的现有模块联合会项目的步骤: 一次给 项目外壳和端口 5000 再来一次 工程 mfe1和端口 3000。 。 。 .
共享 Monorepo 库时的陷阱
语法已失效( 例如 ng 加上 @ angular/ material 或 @ angular/ pwa)
为使模块联合会发挥作用,我们需要同步拖住应用程序。 因此,我们需要把靴子圈的逻辑 转移到一个新的 bootstrap.ts ,然后通过动态导入在 main.ts。这是使用模块联合会时的典型模式。 动态导入使模块联盟可以加载共享的 libs.
然而,一些示意图(如:. ng add @angular/material 或者说 @angular/pwa假设靴子绑住直接发生在 main.ts基于这个原因,有一个图表, 帮助你打开 同步的靴子夹住和关闭:
ng g @angular-architects/module-federation:boot-async false --project yourProject
ng add your-libraries-of-chioce --project yourProject
ng g @angular-architects/module-federation:boot-async true --project yourProject
警告:没有指定所需的版本
如果你得到警告的话 未指定所需的版本, 无法自动确定一个,Module Federation 需要一些帮助来发现共享库的版本以便使用. 原因与同伴依赖关系或使用二级切入点不同 @angular/common/http。 。 。 .
为避免此警告, 您可以用手指定所使用的版本 :
shared: {
"@angular/common": {
singleton: true,
strictVersion: true,
requireVersion: '12.0.0'
},
[...]
},
你也可以使用我们的 share 帮助从您的版本中推断版本编号 package.json 设置时 requireVersion 改为 'auto'数字 :
shared: share({
"@angular/common": {
singleton: true,
strictVersion: true,
requireVersion: 'auto'
},
[...]
})
未导出组件
如果使用共享组件而不通过您的库管导出(index.ts 或者说 public-api.ts),您在运行时得到以下错误:
core.js:4610 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'ɵcmp' of undefined
TypeError: Cannot read property 'ɵcmp' of undefined
at getComponentDef (core.js:1821)