12
votes

The code below can conditionally load a mock service based on different Angular-cli environment variables. However it has a side effect that the mock services get built into the final transcoded and minified output files.

Is there a better way to accomplish lazy loading modules in angular2?

app.module.ts:

import {BrowserModule} from "@angular/platform-browser";
import {NgModule} from "@angular/core";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {environment} from "../environments/environment";
import {XService} from "./xxx.service";
import {XMockService} from "./xxx-mock.service";

let importedModules: Array<any> = [
  XService
];

if (environment.mock) {
  importedModules.push(
    {provide: XService, useClass: XMockService}
  );
} else {
  importedModules.push(
    XService
  );
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: importedModules,
  bootstrap: [AppComponent]
})

export class AppModule {}
2
lazy load angular.io/guide/ngmodule#app-routing use loadChildren : 'app/path/to/YourModuleFileName#YourModuleClassName and in that module you can import other modules to lazy load them ... but w/ import you end up downloading XService and XMockService. I'm looking for a way to download only the modules you want at bootstrapping time based on host using a single code base. hmmJoe Velez

2 Answers

9
votes

You might try something similar to this.

main.ts

platformBrowserDynamic().bootstrapModule(RootModule);

root.module.ts

@NgModule({
  imports: [
    LandingModule,
    UserModule
  ],
  entryComponents: [PageComponent, UserComponent],
})
export class RootModule {

  constructor(private router: Router .....) {
  }

  ngDoBootstrap(ref: ApplicationRef) {
    const isUserPageRequested = this.shouldGoToUser();
    if (isUserPageRequested) {
      this.router.resetConfig(userRoutes);
      ref.bootstrap(UserComponent);
    } else {
      ref.bootstrap(PageComponent);
    }
  }
}

PageComponent is declared in LandingModule and UserComponent is declared in UserModule. This way it is possible to conditionally load module while it works when compiled with aot.

0
votes

I just did like this:

export class AppModule {

  constructor(@Inject(PLATFORM_ID) platformId: Object) {

    if(isPlatformBrowser(platformId)) {
      import('@angular/fire/analytics').then(a => {
        a.provideAnalytics(() => a.getAnalytics())
      });
    }
  }
}