Angular: Include module for specific environment
Daniel Schreiber

Daniel Schreiber @danielsc

Location:
Offenbach, Germany
Joined:
Jul 19, 2019

Angular: Include module for specific environment

Publish Date: Apr 22 '20
8 3

In Angular pre 9 we could do the following to include an optional module only for non prod builds/serves (e.g. a mock http interceptor):

const mockModule = environment.useMockBackend ? [MockModule] : [];

@NgModule({
  imports: [
    CommonModule,
    // ...
    ...mockModule 
  ],
  // ...
})
export class AppModule {
}
Enter fullscreen mode Exit fullscreen mode

With the above setup the CLI would make sure no code of the MockModule would end up in builds for environments where usweMockBackend = false. This is important to keep the bundle size small.

With Ivy (Angular 9+) this doesn’t work any more and the optional module will be part of all builds (even though it might not be used at runtime).

To actually exclude all code of the optional module from builds for specific envionments/configurations, we need to make sure not to import this module directly, but only reference it in the environment*.ts. This works, as the CLI makes sure only the correct file is included in the build:

@NgModule({
  imports: [
    CommonModule,
    // ...
    ...environment.optionalModules
  ],
  // ...
})
export class AppModule {
}
Enter fullscreen mode Exit fullscreen mode

With e.g. environment.ts:

export const environment: Environment = {
  optionalModules: [MockModule],
};
Enter fullscreen mode Exit fullscreen mode

and environment.prod.ts:

export const environment: Environment = {
  optionalModules: [],
};
Enter fullscreen mode Exit fullscreen mode

At hindsight, this seems obvious, but as it did cost me some hours I thought it worth sharing :-)

Bonus

Note, that with the above setup, the optional module cannot/should not reference the configuration in environment.ts as this would induce a circular dependency.
This can be resolved by creating a module factory that takes the needed configuration as parameter, such as:

  public static forRoot(config: OptionalModuleConfig): ModuleWithProviders<MockModule> {
    return {
      ngModule: MockModule,
      providers: [{provide: OPTIONAL_MODULE_CONFIG, useValue: config}]
    };
  }
Enter fullscreen mode Exit fullscreen mode

Comments 3 total

  • jbratu
    jbratuApr 15, 2024

    Cool idea, but it doesn't appear to work in Angular 17, or there is something more to the technique that wasn't documented.

    • Daniel Schreiber
      Daniel SchreiberApr 26, 2024

      What specifically does not work? For me this worked well after upgrading to angular 17

  • hhharm
    hhharmApr 30, 2024

    Thank you, it's exactly what I was looking for!

Add comment