Search code examples
angularangular-routerlazy-loading

Angular, exposing components in lazy-loaded module


My app has LazyModule, that is lazy-loaded, and also RootModule, which lazy-loads this.

When the app navigates to certain route, LazyModule will lazily render its component at <router-outlet> of RootModule`s component while the other <router-outlet>s will expose components by the component property in the route config.

root.component.html:

<!-- super-simplified version -->
<router-outlet name="header"></router-outlet>
...
<router-outlet name="side"></router-outlet>
...
<router-outlet></router-outlet> <!-- primary -->

root.component.ts:

export class RootComponent {
  ...
  // called from somewhere...
  doNavigate() {
    this.route.navigate({outlets: {primary: 'hero', top: 'hero-header', side: 'hero-nav'}})
  }
  ...
}

root.routing.module.ts (route config):

  { path: 'hero', loadChildren: 'app/hero#LazyHeroModule' },
  { path: 'hero-header', component: HeroHeaderComponent, outlet: 'top' },
  { path: 'hero-nav', component: HeroNavComponent, outlet: 'side' }
  // components from 2nd, 3rd lines are declared in *RootModule*

The tricky part is that those route-config-components are semantically related to LazyModule. (They are all hero-related).

It seems ugly to me that HeroHeaderComponent and HeroNavComponent are not part of LazyHeroModule, but part of RootModule. (Am I right??)

I have more lazy-loaded modules that behave similar to LazyModule: Each one of those has corresponding apart-from-family components declared in RootModule:

  // config continues...
  { path: 'villain', loadChildren: 'app/villain#LazyVillainModule' },
  { path: 'villain-header', component: VillainHeaderComponent, outlet: 'top' },
  { path: 'villain-nav', component: VillainNavComponent, outlet: 'side' }
  // components from 2nd, 3rd lines are declared in *RootModule*

If these kind of route configs exists more, I think it is proper to leave root.component.html hosting data from different genres. (hero- or villain-related).

To make it clear, the root of the situation, I think, is that:

  1. I don't want to touch the structure of RootComponent, e.g. the way it hosts header, side and content.
  2. All genres have their own set of interfaces, e.g. Hero genre has hero-header, hero-side hero-content, ... etc, and Villain genre also has corresponding ones.
    • One genre's internal structure of interface A is different from another genre's one.
  3. Some interface(component) of genres involves lazy-loaded module.(for some reason) But I want the other interfaces not requiring lazy-loaded module to be loaded on bootstrap like other components in eager-loaded module.

Here is the question:

Is it possible that lazy-load module bundle up those components which have semantic relationship to itself?

Whether it is or not, Am I approaching the given problem correctly?


The more concretely I write this question, the more I get confused!


Solution

  • I have the same feeling you do, that something is wrong with the current architecture. I would put all of the hero stuff in the Hero module. So if HeroModule is lazy loaded, all that stuff (HeroHeader and HeroNav) will be lazy-loaded too.

    So I would have a single outlet in RootComponent, and in each of the modules that get loaded within it, I would have the top and side as well as the primary children outlets.