首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角模块联盟:如何为每个远程模块配置隔离路由?

角模块联盟:如何为每个远程模块配置隔离路由?
EN

Stack Overflow用户
提问于 2022-04-08 17:09:12
回答 1查看 4.2K关注 0票数 2

我想实现一个隔离路由为每个远程模块的Webpack模块-联邦角应用程序。

每个遥控器都有自己的路由模块,但是根据传递给router.navigaterouterLink的URL,远程也可以覆盖基本URL,这个基本URL应该专门负责主机/shell应用程序。

例如。

  • shell是在localhost:4200
  • remote-a公开的,localhost:4201
  • remote-b是公开的,localhost:4201
  • remote-b是公开的,localhost: 4202
  • remote-a是由shell导入的,localhost:4200/remote-a
  • remote-b是由shell导入的,localhost:4200/remote-b.

是公开的。

我想要的:

每个应用程序的路由都应该是独立的,而且remote;

  • remote-a不应该能够更改其作为remote;

  • remote-b的基本URL localhost:4200/remote-a,当用作远程时不应该能够更改基本URL localhost:4200/remote-b

我们如何限制每个远程模块路由的行为,使其只能够相对于自己的路径执行导航,而不允许它干扰其他远程设备和shell/主机应用程序?

更新

基于我发现的一些文章

似乎更接近的解决办法如下:

如果你的微前端带来了自己的路由器,你需要告诉你的外壳,微前端将附加更多的片段到网址。为此,您可以使用@ startsWith -architects/模组联合工具提供的匹配器:

代码语言:javascript
复制
import { 
    startsWith, 
    WebComponentWrapper, 
    WebComponentWrapperOptions 
} 
from '@angular-architects/module-federation-tools';

[...]

export const APP_ROUTES: Routes = [
    [...]
    {
        matcher: startsWith('angular3'),
        component: WebComponentWrapper,
        data: {
            [...]
        } as WebComponentWrapperOptions
    },
    [...]
}

为了使此工作,在这里使用的路径前缀angular3也需要由微前端使用。由于路由配置只是一个数据结构,您将找到动态添加它的方法。

你能否进一步解释一下这个解决方案是如何工作的,以及它是否能满足我的要求?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-15 11:19:41

解决方案取决于您希望将遥控器和外壳连接得有多紧密,以及您希望在哪里设置对路由和导航的控制。我成功地使用了以下方法:

time

  • (optional)
  • Shell应用程序不知道它可以加载的远程处理程序的任何细节,只有MF远程信息和每个远程应用程序的baseHref路由。
  • 远程应用程序不知道任何关于shell的信息,也不知道任何其他可能由shell
  • 加载的远程应用程序,只有一个具有路由的远程模块可以在 mflib中的任何一点上处于活动状态--您的共享库,用于在shell和远程服务器、帮助函数等之间进行通信。

远程应用程序将您想要公开的远程部分放置到一个专门的NGModuleFeatureModule中,该模块为其组件导入RouterModule.forChild和设置路由。

代码语言:javascript
复制
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中有两个相应的路由

代码语言:javascript
复制
const MY_ROUTES =[
{ 
    path: '', 
    component: RemoteAComponent, 
    pathMatch: 'full'
},
{ 
    path: 'orders', 
    component: OrdersComponent
}
]

在急切模式下,您可以通过AppModule通过RouterModule.forRoot(MY_ROUTES)设置此路由,然后可以使用http://localhost:4201http://localhost:4201/orders导航到这些路由(前提是您没有设置不同的BASE_HREF.)。或者,可以使用延迟加载将这些路由设置为某些根路径的子路由。

代码语言:javascript
复制
//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文件等等。

代码语言:javascript
复制
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属性。例如:

代码语言:javascript
复制
//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将得到以下路由树:

代码语言:javascript
复制
/                  -> 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时,您可以将一些值放到服务中,并且可以在远程模块中读取它们)

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71800882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档