1

I'm using the latest Angular CLI build (16) and I'm trying to lazy load routes but it fails for some reason, I can't find any new questions or solutions for this.

Folder structure:

folder structure

core.component.html:

<router-outlet></router-outlet>

core.component.ts:

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {RouterModule} from '@angular/router';

// Modules
import {AdminAreaModule} from './+admin-area';

// Services
import {GlobalsService, RegexService, UtilsService} from './shared';

// Main app component
import {CoreComponent} from './core.component';

@NgModule({
  imports: [
    BrowserModule,

    // Feature modules
    AdminAreaModule
  ],
  exports: [
    BrowserModule
  ],
  declarations: [
    CoreComponent
  ],
  providers: [
    GlobalsService,
    RegexService,
    UtilsService
  ],
  bootstrap: [CoreComponent]
})
export class CoreModule {}

admin-area-router.module.ts:

import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';

// Global modules
import {ComponentsModule, SharedModule} from '../../shared';

// Lazy loaded modules
import {AdminAreaModule} from '../admin-area.module';

@NgModule({
  imports: [
    RouterModule.forChild([
      {
        path: 'admin',
        loadChildren: 'app/+admin-area/admin-area.module#AdminAreaModule'
      }
    ])
  ],
  exports: [
    RouterModule
  ]
})
export class AdminAreaRouterModule {}

admin-area.module.ts:

import {NgModule} from '@angular/core';

import {AdminAreaRouterModule} from './router';

import {ComponentsModule, SharedModule} from '../shared';

@NgModule({
  imports: [
    ComponentsModule,
    SharedModule,

    // Feature modules
    AdminAreaRouterModule
  ],
  exports: [
    ComponentsModule,
    SharedModule,
    AdminAreaRouterModule
  ]
})

export class AdminAreaModule {}

This throws an error:

Error in ./CoreComponent class CoreComponent - inline template:0:0 caused by: No provider for RouterOutletMap!

Why am I getting this error when I clearly have a router-outlet in my core.component.ts file?

Chrillewoodz
  • 27,055
  • 21
  • 92
  • 175

2 Answers2

2

You don't have routing defined in the core module, but you do have a router-outlet.

Hence the error no provider (aka no routing is provided) for routeroutletmap (router-outlet)

Even if you have routing in your submodule (in this case, the admin module), you also need to add routing to the core module. For example, { path: '', redirectTo: '/admin', pathMatch: 'full' }

koningdavid
  • 7,903
  • 7
  • 35
  • 46
  • That just gives me `Maximum callstack exceeded` :| – Chrillewoodz Oct 18 '16 at 13:13
  • Basically what I have is two parts of the site, an admin area and the normal site. I want `'/'` or `''` to be the normal site, and `/admin` to be the admin part of the site. So I've made two modules with their own routing. Do I lazy load `/` and `/admin` in the core module? And then their respective children in their own routing files? – Chrillewoodz Oct 18 '16 at 13:17
  • @Chrillewoodz yes, you would lazy load / and /admin in the core module, the respective children should be bundled in the lazy loaded modules. – koningdavid Oct 18 '16 at 13:43
  • @Chrillewoodz I have a working example here: https://github.com/daviddt/angular2-lazy-load-example/tree/master/src As you can see I also defined routing in the root module. Do note that this is routing forRoot and not routing forChild – koningdavid Oct 18 '16 at 13:44
  • Ok got it working now and i understand more of how it works. Big thanks man you were a life saver. – Chrillewoodz Oct 19 '16 at 04:55
1

This is not how routing works. The router with loadChildren going to admin should not be inside admin. It should be in a higher level, for example, in core.

As a side effect of that, when you import the router in core, you'll get all the directives from that module, including router-outlet.

See this repository here to see how routing lazy loading works:
https://github.com/meligy/routing-angular-cli

In this repo, app is similar to your core, and lazy is similar to your admin.

AppRoutingModule is in the NgModule imports of AppModule. AppRoutingModule has a route that looks like this:

  {
    path: 'lazy',
    loadChildren: './lazy/lazy.module#LazyModule'
  }

(yes, you can define paths relatively, as of beta-17)

Then, inside the /lazy folder, LazyRoutingModule is in the NgModule imports of LazyModule.

LazyRoutingModule has all the routes inside /lazy. It doesn't know it's going to be /lazy. Only AppRoutingModule knows that.

LazyRoutingModule only knows that whatever path the AppRoutingModule chooses for it, LazyRoutingModule will control the child routes it defines under that.

That's why AppRoutingModule is defined like this:

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: []
})
export class AppRoutingModule { }

While LazyRoutingModule is defined as:

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
  providers: []
})
export class LazyRoutingModule { }

Note the forRoot() vs the forChild().

With that all translated to your project words (again, app becomes core, and lazy becomes admin, if I understand your project structure right), you should be able to lazy load the admin folder.

Let me know how it goes.

Meligy
  • 35,654
  • 11
  • 85
  • 109
  • Great answer and I managed to get it to work finally. One thing I'm in the dark about though is that I can see the chunks being loaded on demand, but only the first time I switch to a particular view. If I navigate away and then come back, does the chunks stay in the memory or how does that actually work? When navigating away it shouldn't know about the lazy loaded module anymore right? – Chrillewoodz Oct 19 '16 at 04:56
  • I think it stays from what I remember, looking at the network in Chrome dev tools. – Meligy Oct 19 '16 at 06:25
  • Alright. Could you have a look at this http://stackoverflow.com/questions/40122820/angular-2-how-to-define-lazy-loaded-child-routes-of-a-parent-route-thats-also-l? – Chrillewoodz Oct 19 '16 at 06:27