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 {
}
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 {
}
With e.g. environment.ts
:
export const environment: Environment = {
optionalModules: [MockModule],
};
and environment.prod.ts
:
export const environment: Environment = {
optionalModules: [],
};
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}]
};
}
Top comments (3)
Thank you, it's exactly what I was looking for!
Cool idea, but it doesn't appear to work in Angular 17, or there is something more to the technique that wasn't documented.
What specifically does not work? For me this worked well after upgrading to angular 17