DEV Community

Daniel Schreiber
Daniel Schreiber

Posted on

Angular: Include module for specific environment

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

Top comments (3)

Collapse
 
hhharm profile image
hhharm

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

Collapse
 
jbratu profile image
jbratu

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

Collapse
 
danielsc profile image
Daniel Schreiber

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