我想实现一个隔离路由为每个远程模块的Webpack模块-联邦角应用程序。
每个遥控器都有自己的路由模块,但是根据传递给router.navigate或routerLink的URL,远程也可以覆盖基本URL,这个基本URL应该专门负责主机/shell应用程序。
例如。
localhost:4200localhost:4201localhost:4201localhost: 4202localhost:4200/remote-alocalhost:4200/remote-b.是公开的。
我想要的:
每个应用程序的路由都应该是独立的,而且remote;
remote-a不应该能够更改其作为remote;
remote-b的基本URL localhost:4200/remote-a,当用作远程时不应该能够更改基本URL localhost:4200/remote-b;我们如何限制每个远程模块路由的行为,使其只能够相对于自己的路径执行导航,而不允许它干扰其他远程设备和shell/主机应用程序?
更新
基于我发现的一些文章
似乎更接近的解决办法如下:
如果你的微前端带来了自己的路由器,你需要告诉你的外壳,微前端将附加更多的片段到网址。为此,您可以使用@ startsWith -architects/模组联合工具提供的匹配器:
import {
startsWith,
WebComponentWrapper,
WebComponentWrapperOptions
}
from '@angular-architects/module-federation-tools';
[...]
export const APP_ROUTES: Routes = [
[...]
{
matcher: startsWith('angular3'),
component: WebComponentWrapper,
data: {
[...]
} as WebComponentWrapperOptions
},
[...]
}为了使此工作,在这里使用的路径前缀angular3也需要由微前端使用。由于路由配置只是一个数据结构,您将找到动态添加它的方法。
你能否进一步解释一下这个解决方案是如何工作的,以及它是否能满足我的要求?
发布于 2022-04-15 11:19:41
解决方案取决于您希望将遥控器和外壳连接得有多紧密,以及您希望在哪里设置对路由和导航的控制。我成功地使用了以下方法:
time
baseHref路由。远程应用程序将您想要公开的远程部分放置到一个专门的NGModuleFeatureModule中,该模块为其组件导入RouterModule.forChild和设置路由。
src/app/
|-app.module.ts # your main module, - not exposed as mf remote
|-feature.module.ts # your feature module, exposed as mf remote
|-orders.component.ts
|-remote-a.component.ts
...当您将Remote-A应用程序作为独立应用运行时,您可以将您的FeatureModule急切地导入到主AppModule中(或者懒散地将您的调用根据用例进行,如果您有更多的模块等等)。如果您使用标准(急切)导入,那么您可以在根模块中设置RouterModule.forRoot,使用您想要的任何路径导航到FeatureModule的组件。如果您延迟导入,那么RouterModule.forChild中定义的路由将相对于将此模块延迟加载到根路由器的基本路径。您需要确保,无论您在特性模块中的任何地方导航,都使用相对导航(例如this.router.navigate(['items'], { relativeTo: this.route }))。例如,假设在Remote-A项目中有两个组件,在FeatureModule中有两个相应的路由
const MY_ROUTES =[
{
path: '',
component: RemoteAComponent,
pathMatch: 'full'
},
{
path: 'orders',
component: OrdersComponent
}
]在急切模式下,您可以通过AppModule通过RouterModule.forRoot(MY_ROUTES)设置此路由,然后可以使用http://localhost:4201或http://localhost:4201/orders导航到这些路由(前提是您没有设置不同的BASE_HREF.)。或者,可以使用延迟加载将这些路由设置为某些根路径的子路由。
//app.module.tsm import section:
RouterModule.forRoot([
{
path: '',
component: HomeComponent
},
{
path: 'feature',
loadChildren: () => import('./feature.module').then(m => m.FeatureModule)
}
])
//feature.module.ts
RouterModule.forChild(MY_ROUTES)现在要访问OrdersComponent,您可以使用http://localhost:4201/feature/orders,因为在我们的FeatureModule中定义的所有路由相对于父路由的子路由,在本例中是/feature/
这样,您的FeatureModule加载在哪个根url下并不重要,它的内部路由将相对于根URL正确解析。
对于其他遥控器,请确保使用forChild路由器设置,将实际的远程模块提取到专用的角度模块中。
Shell:您需要以某种方式定义可用的远程组件--静态配置,或者动态构造它,例如,通过对某个注册表端点进行HTTP调用,加载JSON文件等等。
const microFrontends = [
{
baseUrl: "remote-a", //where should we append this to router
moduleName: "FeatureAModule" //name of NG module class in your remote
remoteEntry: 'http://localhost:4201/remoteEntry.js', //remote webpack url
remoteName: 'remotea', //name of the remote module,
exposedModule: './FeatureAModule', //exposed module inside the webpack remote
},
{
baseUrl: "remote-b",
moduleName: "FeatureBModule"
remoteEntry: 'http://localhost:4202/remoteEntry.js',
remoteName: 'remoteb',
exposedModule: './FeatureBModule',
}
]接下来,为远程用户定义路由--包括shell应用程序中组件的内部路由和远程模块的路由--您只指定RemoteModule应该插入其子路由的根路径,然后使用Manfred @angular-architects/module-federation lib中的loadRemoteModule fn指定loadRemoteModule属性。例如:
//app.module.ts
RouterModule.forRoot([
{
path: '', //this is an example internal route to component that exists inside shell app
component: HomeComponent,
pathMatch: 'full'
},
//we map each microfrontend entry to a lazy loaded Route object,
...microFrontends.map(mf=> ({
path: mf.baseUrl, // we insert any routes defined in the remote module we load
//as children of `mf.baseUrl` route
loadChildren: () => loadRemoteModule(mf).then(m => m[mf.moduleName])
}))
])使用上面的示例配置,shell将得到以下路由树:
/ -> shell/HomeComponent.ts
/remote-a -> lazy loaded module FeatureAModule from remote-a remote
/ -> remote-a/FeatureModule/remote-a.component.ts
/orders -> remote-a/FeatureModule/orders.component.ts 外壳可以在任何URL下挂载远程模块,例如foobar,然后导航到远程orders组件-a我们将使用/foobar/orders。因此,shell完全控制根路由/url结构,远程控制其子树中的路由/url。
如果您需要进行绝对导航,或者在Shell和Remotes之间进行通信,请创建一个具有共享角度模块的共享角度库,并通过单例服务(providedIn: root)进行通信。
现在,您无法在加载远程模块时将参数或DI令牌传递给远程模块(在角度上存在一个问题),因此,如果您的子/远程模块需要知道在什么URL /路由下挂载了它,则需要天真地解析浏览器URL,并假定路径的第一部分是根路径,或者使用共享服务(在shell中,当调用loadChildren时,您可以将一些值放到服务中,并且可以在远程模块中读取它们)
https://stackoverflow.com/questions/71800882
复制相似问题