Angular - Import both BrowserAnimationsModule and NoopAnimationsModule and decide what to use at runtime (using AOT)

Viewed 1408

The problem is:

I want to import the NoopAnimationsModule only when I'm on an IE. In my app.module's imports array I have something like:

imports: [AppConfig.IS_IE ? NoopAnimationsModule : BrowserAnimationsModule, .... ]

This works during the development but not in the production. I guess it has to do about the AOT compilation when the import gets place before the code reaches the browser.

I came to the conclusion that I have to import both of them and configure something the during the runtime in order to decide which module's providers should I use.

Keep in mind that both of these modules provide the same services but with differences in order to change the way Angular handles the animation.

Is there a way to implement this idea?

1 Answers

That's interesting. You are right though that aot used to prevent this, but as far as I know, with ivy, it should already be possible to do it your way, but I'm not sure.

Just tested and you are right, with a dynamic value like that, it doesn't work yet

If you have at least angular 9 you can do the following:

So I assume your AppConfig.IS_IE gets set before the animation module is imported. Looking at the source code I believe you could do something like this by creating a custom animations module. This uses a special property ɵinj, which is not part of the public API, so it's subject to change:

@NgModule({
  exports: [BrowserModule],
})
export class ConfigAnimationsModule {
  static forRoot(isIE: boolean) {
    return {
      ngModule: ConfigAnimationsModule,
      providers: isIE
        ? NoopAnimationsModule.ɵinj.providers
        : BrowserAnimationsModule.ɵinj.providers
    };
  }
}

which you can then import:

imports: [
  ConfigAnimationsModule.forRoot(AppConfig.IS_IE),
  //...
]

For angular version <= 8 you can use the private property ngInjectorDef. Untested though, so your mileage may vary:

@NgModule({
  exports: [BrowserModule],
})
export class ConfigAnimationsModule {
  static forRoot(isIE: boolean) {
    return {
      ngModule: ConfigAnimationsModule,
      providers: isIE
        ? NoopAnimationsModule['ngInjectorDef'].providers
        : BrowserAnimationsModule['ngInjectorDef'].providers
    };
  }
}
Related