APP_INITIALIZER factory is not running at all when configured within Angular library

Viewed 701

Example Code in library:

export function appSettingsLoader(): () => Promise<unknown> {
  console.log('i should run first')
  const func = function () { return Promise.Resolve()) };
  return func;
}

@NgModule({
  imports: [
    MsalModule
  ]
})
export class MsalAuthenticationModule {
  public static forRoot(options: {
    config: Type<IMsalConfigurationService>
  }): ModuleWithProviders {
    return {
      ngModule: MsalAuthenticationModule,
      providers: [
        {
          provide: APP_INITIALIZER,
          useFactory: appSettingsLoader,
          deps: [],
          multi: true
        }
      ]
    };
  }
}

Code in app module:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    MsalAuthenticationModule.forRoot({ config: Config })
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

At no point will I ever see my console.log.

EDIT:

from comments, I decided to try and reproduce with a new angular app with a library inside the same app under projects. To my surprise the app_initializer worked.

So I then used NPM Link on that working library and imported the module from there into my actual app (a different workspace). It didnt work.

This tells me that app_initializer can only work when the library is inside the same project, which makes app_initializer worthless for me.

It seems incorrect but this is what I observed.

1 Answers

The issue comes from multiple module bundling - library got wrong directory for angular node modules (was using the library workspace node_modules folder) even when using it via npm link to simulate a publish.

Added this to my client app which uses the library within tsconfig compile options:

"paths": {
  "@angular/*": [
    "./node_modules/@angular/*"
  ]
}

problem resolved.

Clearly the library must make use of exactly the same node modules in order to hook into such initialization hooks.

Edit:

I had even more problems. If you have 2 app_initializers a and b, a is asynchronous and b depends on a, the app will not wait for the a to resolve, and so b will throw errors. To resolve that I used the injector in b.

Related