Add loaded routes from REST in runtime
See original GitHub issueThere’s a bug when adding routes dynamically using router.resetConfig()
method. I’m not sure if it’s a bug in Angular-CLI, Angular compiler, Angular Router or Webpack, please guide me.
This is the setup:
## routes.json
[
{ "path": "contact", "loadChildren": "./contact/contact.module#ContactModule" }
]
## RouterService.ts
getRotues() {
return this._http.get('routes.json')
.map((res) => res.json())
}
Now to the actual bug:
let routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full'},
{ path: 'home', loadChildren: './home/home.module#HomeModule' }
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ]
})
export class AppModule {
constructor(private router:Router, private routerService:RouterService) {
// This works
// Pushing the same route as in routes.json
// ----------------------
routes.push({ path: 'contact', loadChildren: './contact/contact.module#ContactModule' })
router.resetConfig(router);
// This does not work
// Loads json data from service and push the new route
// ----------------------
this.routerService.getRoutes().subscribe((result) => {
result.forEach((route) => {
routes.push({ path: route.path, loadChildren: route.loadChildren })
});
this.router.resetConfig(routes);
});
// This does works
// By just console log this anonymous object, the loaded routing from the
// json data will work.
// ----------------------
console.log({ loadChildren: './contact/contact.module#ContactModule' })
this.routerService.getRoutes().subscribe((result) => {
result.forEach((route) => {
routes.push({ path: route.path, loadChildren: route.loadChildren })
});
this.router.resetConfig(routes);
});
}
Please provide us with the following information:
OS?
Windows 7
Versions.
Please run
ng --version
. If there’s nothing outputted, please run in a Terminal:node --version
and paste the result here: angular-cli: 1.0.0-beta.21 (Also tried with Angular-cli 1.0.0-beta.26 with same result) node: 5.8.0 os: win32 x64
Repro steps.
The app was created by Angular-CLI, setup already described.
The log given by the failure.
Error: Uncaught (in promise): Error: Cannot find module ‘./contact/contact.module’. Error: Cannot find module ‘./contact/contact.module’. at webpackAsyncContext (main.bundle.js:64815) at SystemJsNgModuleLoader.loadAndCompile (main.bundle.js:73204) at SystemJsNgModuleLoader.load (main.bundle.js:73196) at RouterConfigLoader.loadModuleFactory (main.bundle.js:20568) at RouterConfigLoader.load (main.bundle.js:20559) at MergeMapSubscriber.project (main.bundle.js:76506) at MergeMapSubscriber._tryNext (main.bundle.js:16175) at MergeMapSubscriber._next (main.bundle.js:16165) at MergeMapSubscriber.Subscriber.next (main.bundle.js:440) at ScalarObservable._subscribe (main.bundle.js:41699) at webpackAsyncContext (main.bundle.js:64815) at SystemJsNgModuleLoader.loadAndCompile (main.bundle.js:73204) at SystemJsNgModuleLoader.load (main.bundle.js:73196) at RouterConfigLoader.loadModuleFactory (main.bundle.js:20568) at RouterConfigLoader.load (main.bundle.js:20559) at MergeMapSubscriber.project (main.bundle.js:76506) at MergeMapSubscriber._tryNext (main.bundle.js:16175) at MergeMapSubscriber._next (main.bundle.js:16165) at MergeMapSubscriber.Subscriber.next (main.bundle.js:440) at ScalarObservable._subscribe (main.bundle.js:41699) at resolvePromise (main.bundle.js:101365) at resolvePromise (main.bundle.js:101350) at main.bundle.js:101399 at ZoneDelegate.invokeTask (main.bundle.js:101162) at Object.onInvokeTask (main.bundle.js:36074) at ZoneDelegate.invokeTask (main.bundle.js:101161) at Zone.runTask (main.bundle.js:101051) at drainMicroTaskQueue (main.bundle.js:101298) at HTMLElement.ZoneTask.invoke (main.bundle.js:101236)
Mention any other details that might be useful.
Thanks! We’ll be in touch soon.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:12
- Comments:38 (5 by maintainers)
So there is no plan to support such feature from AngularCLI level? I am writing big enterprise app and such feature is crucial for me.
This is a feature request for the compiler internal API (in Angular repo, mostly maintained by CLI people). I’m not expecting it to happen any time soon I’m afraid.
Let me explain how I understand this process works, having worked on the implementation of the first two steps myself recently:
In build time, the compiler goes by
NgModule
decorator to find all theloadChildren
lazy module file paths so that Webpack can generate separate bundles for them later.It also stores a mapping between the
loadChildren
strings and the actual file paths and symbols (module class names)Some webpack magic happens and translates the file paths to the correct bundle files
In runtime, the router gets a map, where the keys are the exact strings in
loadChildren
and the values are the file paths after transformation to bundles and of course class namesThe problem in your scenario is that none of the build steps happened. The router doesn’t know where to load the files from except in a SystemJS-like way (resolving a URL relative to root), and there are no files to match that in output folder (/dist).
The compiler needs a static way of knowing about the loadChildren entries so that it can create the mapping above, and also create separate bundles for the lazy-loaded routes.