nx
nx copied to clipboard
virtual router token injection omitted for mfe architecture
SUBJECT: virtual router token injection omitted for mfe architecture
Current Behavior
this is about routing across the mfe spectrum and maintaining router context
Nx inspired manner to navigate across the mfe spectrum is to just use the router
- '/host-my-app'
- '/remote-cart'
- '/remote-home'
But the host
Expected Behavior
A mechanism shold be implemented to virtualize mfe intended routers away from the isolated/separated (by nature) the browser dom. This was solved manually by Kyle Cannon in plain angular identifying this natural breach by angular alone
https://www.youtube.com/watch?v=fQrUGill9M0&ab_channel=ng-conf
https://github.com/kylecannon/angular-dream-stack
Nx should be guaranteeing our mfe routers 's are not victim to the gobbling up nature of plain angular or the browser
Steps to Reproduce
implement a side-nav with links and a right hand side canvas all pointing to mfe routes click link in side-nav the entire page gets loaded instead of punched into the canvas WHY? because the host router config (which is needed on load) gobbles up all subsequent routes
Are standard plain vanilla named outlets the way forward to solve this?
Thanks for an elite product and any advice forward
more forum gabb on this issue
Im finding I cannot just route anywhere across mfe's... my host
Environment
nx report
NX Report complete - copy this into the issue template
Node : 16.17.0 OS : darwin arm64 yarn : 1.22.18
nx : 14.6.4 @nrwl/angular : 14.6.4 @nrwl/cypress : 14.6.4 @nrwl/detox : Not Found @nrwl/devkit : 14.6.4 @nrwl/eslint-plugin-nx : 14.6.4 @nrwl/express : Not Found @nrwl/jest : 14.6.4 @nrwl/js : 14.6.4 @nrwl/linter : 14.6.4 @nrwl/nest : Not Found @nrwl/next : Not Found @nrwl/node : 14.6.4 @nrwl/nx-cloud : 14.6.1 @nrwl/nx-plugin : 14.6.4 @nrwl/react : Not Found @nrwl/react-native : Not Found @nrwl/schematics : Not Found @nrwl/storybook : 14.6.4 @nrwl/web : 14.6.4 @nrwl/workspace : 14.6.4 typescript : 4.7.4
Local workspace plugins:
Community plugins: @fortawesome/angular-fontawesome: 0.10.2 @ngrx/component-store: 14.2.0 @ngrx/effects: 14.2.0 @ngrx/entity: 14.2.0 @ngrx/router-store: 14.2.0 @ngrx/store: 14.2.0 apollo-angular: 4.0.1 @buildmotion/angular: 13.0.1 @ngrx/schematics: 14.2.0 @ngrx/store-devtools: 14.2.0 @storybook/angular: 6.5.10
Can you provide a repository with what you have so far so I can take a look?
It also might help me understand the problem better. I'm not entirely sure what you mean by "gobbling up all subsequent routes".
To me it almost sounds like you want a child router-outlet that should load the contents of a side-nav page. This still feels like it could be solved using Angular primitives, but I need a repository of the problem to understand and investigate this issue.
Thanks Colum,
Im under way too much at this time to carve out a repo on this. My apologies. Things just got shutdown because of this lapse in functionality with mfe and Nx monorepo shelved at this time. I can attempt to resurrect but they want a solution to this asap.
Have you checked out Kyle Cannon's video? I mean its fairly easy to see what he implemented. A virtual dom coupled router obfuscator by a singleton root token injected router thats virtual across all MFE's. My sidenav is precisely how you stated with an embedded router-outler but since the browser and dom are dominating the routing (app/host/remote & its router) the host router is always the one who started routing on boot and subsequent routes thru the routing have to go back to the host for any/every remote.
I had hoped Nx implemented this mechanism via a static mfe vs dynamic mfe (if such a thing exists maybe I need to check nxconsole and check)(which would imply static router token injected or dynamic browser dom router)
Anyway heres a blip of what I got
HOST (app.routing.module.ts)
const routes: Routes = [
{
path: '',
redirectTo: '/remote-auth',
pathMatch: 'full',
},
{
path: 'remote-auth',
loadChildren: () =>
loadRemoteModule('remote-auth', './Module').then(
(m) => m.RemoteEntryModule
),
},
{
path: 'remote-nav',
canActivate: [AuthenticatedGuard],
loadChildren: () =>
loadRemoteModule('remote-nav', './Module').then(
(m) => m.RemoteEntryModule
),
}
}
Login module loads fine I authenticate and control yeilds back to the host because login module routed (as you advised) using this cmd
this.router.navigate(['/remote-nav']);
so that route takes control back to the host code above shows where this route causes the host to navigate to which mfe and lazy load and its the NAV
Nav module loads fine but it does not get projected into the correct
because this is the host template
<router-outlet></router-outlet>
and so my nav template, this is the child router-outlet that should load the contents of a side-nav page see below the
<div id="shell-template">
<div id="navbar">
<wexinc-side-nav
[navTitle]="navTitle"
[navMainIcon]="navMainIcon"
[navItems]="navItems"
>
<ng-content navTitle select="[navTitle]"></ng-content>
<ng-content navSmallTitle select="[navSmallTitle]"></ng-content>
</wexinc-side-nav>
</div>
<div id="content">
<router-outlet></router-outlet>
</div>
</div>
and its
this obviates the need for virtual token injected routers to obfuscate the browser dom associated to each app/router no?
watch the video it really makes sense
and I need to know if Nx team implemented this mechanism or now
or what Im suppose to do at this point
Thank you
To me it almost sounds like you want a child router-outlet that should load the contents of a side-nav page.
I already have that Colum, see above. The MFE is a lazy loaded child route targeting the next router-outlet to encounter which now appears HAS TO BE GOVERNED by the host? Yes? and thats how its getting gobbled.
The only thing I can spot inside nxconsole that might be something but I think im wrong
@nrwl/angular:host
is this parameter below
dynamic
boolean
Default: false
Should the host application use dynamic federation?
and I think this only has to do with locating the actual module of the mfe and nothing to do with token based virtual routing across all MFE's
so this is a major show stopper for us
nothing offered inside @nrwl/angular:remote
either
any help is greatly appreciated.
I need to see your NavigationModule
We view Federated apps as one single app, so there should only be one router. It's set up as a singleton across all places. So if your child routing setup has been done correctly, i.e. your remote app is using a router outlet with named router-outlet, then it should work fine
Okay I will provide that... but this discussion has a repo asking for this very thing too just for reference thanks Colum https://github.com/nrwl/nx/issues/7268
Here is the app.module for remote named /remote-nav
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
RouterModule.forRoot(
[
{
path: '',
canActivate: [AuthenticatedGuard, RoleGuard],
loadChildren: () =>
import('./remote-entry/entry.module').then(
(m) => m.RemoteEntryModule
),
},
],
{ initialNavigation: 'enabledBlocking' }
),
],
providers: [AdminGuard, RoleGuard, AuthenticatedGuard],
bootstrap: [AppComponent],
})
export class AppModule {}
and here is his entrymodule
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule.forChild([
{
path: '',
canActivate: [AuthenticatedGuard],
loadChildren: () =>
import('@wexinc/shared-root-ui-components').then(
(m) => m.ComponentsModule
),
},
]),
],
providers: [],
})
export class RemoteEntryModule {}
we are lazy loading shared modules inside libs who have routes themselves
Okay I will provide that... but this discussion has a repo asking for this very thing too just for reference thanks Colum https://github.com/nrwl/nx/issues/7268
We view Federated apps as one single app, so there should only be one router. It's set up as a singleton across all places. So if your child routing setup has been done correctly, i.e. your remote app is using a router outlet with named router-outlet, then it should work fine
Thanks Colum.... I appreciate your assertion but what Im seeing is the route is being gobbled up by the host
Well this is good news fed apps are one big single app and one router singleton thats promising.
My route is still being gobbled up though
So the lazy loaded Navigation module should have an empty index route of single quotes as follows just like a lazy loaded feature module
path: '',
and your saying it might need to be
path: 'remote-nav',
?
Our goal is to also be able to alter the url by hand and enter REST urls like
http://localhost:4200/user/1
http://localhost:4200/user/2
http://localhost:4200/user
Okay so named outlets was one option I wanted to consider
Is there a convention to keep it in sync with the route hierarchy?
can I call the named outlet the name of the remote? Is that safe?
@kenatwex Can you take a look at my repo, where I have tried to create an example based on what you've said, to determine what the key differences are?
This repo uses
Host -> Remote -> Lazy Loaded Side Nav -> Lazy loaded pages into portion beside Side Nav
https://github.com/Coly010/nx-ng-mf-route
Hi Colum,
Im rendering my sidenav and still not projecting yet due to this small issue Im knocking on the door of finishing this... but Im really stuck.
routers can project components, redirects, modules
but MFE's ?
here is my routeconfig for my UI module below
FACT: both attempts to load my dashboard (which should punch into the content pane right hand side) are below and yeild errors
QUESTION: Is it legal from the libs area to load MFE's from apps folder? I feel strange about it and had to define tsconfig paths to get those
How can I successfully load an MFE from libs folder UI.MODULE.ts
LIBS/UI.MODULE.TS
const routes: Routes = [
{
path: '',
component: NavigationComponent,
children: [
{
path: 'remote-nav/remote-dashboard',
outlet: 'content',
canActivate: [AuthenticatedGuard],
// loadChildren: () =>
// import('@wexinc/remote-dashboard/app/remote-entry/entry.module').then((m) => m.RemoteEntryModule),
loadChildren: () =>
loadRemoteModule('remote-dashboard', './Module').then(
(m) => m.RemoteEntryModule
),
}
}
]
}
crbug/1173575, non-JS module files deprecated.
is the error from latter attempt above
the attempt commented out was yeilding rootDir errors complaining about the remoteEntryModule not living under the root folder of libs
Hi COlum,
I should be able to do this from my libs/auth.module
{
path: 'remote-nav',
canActivate: [AuthenticatedGuard],
loadChildren: () =>
loadRemoteModule('remote-nav', './Module')
.then((m) => m.RemoteEntryModule)
},
and im receiving this errors
Error: Uncaught (in promise): Error: Call setRemoteDefinitions or setRemoteUrlResolver to allow Dynamic Federation to find the remote apps correctly. Error: Call setRemoteDefinitions or setRemoteUrlResolver to allow Dynamic Federation to find the remote apps correctly.
I have all the remotes listed in my module.federation.config.js
module.exports = {
name: 'host',
remotes: [
'remote-dashboard',
'remote-nav',
'remote-auth',
]
};
why isnt dynamic federations finding my remotes?
You don't need dynamic federation in your case. You just need a standard import
Can MFE's survive router transclusion into any outlet positioned anywhere on a single page? Im wondering is Kyle Cannon's work needs attention in Nx. We are transcluding (projecting) entire MFE's into outlet's everywhere.
Is this legal with current Nx release on this MFE stuff or are there limitations?
Thank you
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! 🙏
This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.