简体   繁体   中英

How to load a remote config file for a lazy loaded module in Angular

I have an Angular (v6) SPA with a number of lazily loaded modules. At present I have a json file holding config for the app that can be changed via a separate admin interface, without requiring a rebuild/deploy of the app. The config file is currently loaded in the APP_INITIALIZER, which works well to ensure I retrieve the config before allowing the app to fully bootstrap.

I want to split this config file up per module, having one general config loaded in the APP_INITIALIZER and only load the others when that particular module is lazy loaded.

Is there an accepted or best practice way to do this? I can't seem to find anything in the angular docs or in general on the net. One approach may be to fetch the config in the modules constructor, but as far as I can see, there is no way for me to prevent the module continuing to load and setup all its components etc until after this config file is retrieved and stored somewhere.

Could a route resolver serve this purpose perhaps, if I set it on the root route for the lazy loaded module? Eg Instead of returning any data, I could inject some "ConfigService" into the resolver, which will retrieve the appropriate config file and store it, and then let the resolver resolve.

Then components in this module could inject this same ConfigService, getting access to whatever config points were retrieved.

Fetching the configuration during module initialization (either in the constructor or in a static method such as forRoot ) is not going to work, as dependencies have not been resolved at that point. So, for example, you won't have HttpClient available to fetch data.

What could be a viable way:

1. Provide a ConfigurationService that gets the URL of your config file injected

@Injectable()
export class ConfigService {

  private config$ = new BehaviorSubject<any | null>(null);
  private loadedConfig = false;

  constructor(@Inject(CONFIG_URL) private configUrl: string,
              private httpClient: HttpClient) {
    this.getConfig();
  }

  getConfig(): Observable<any> {
    if (!this.loadedConfig) {
      this.loadedConfig = true;
      this.httpClient.get(this.configUrl).subscribe(this.config$);
    }
    return this.config$;
  }

}

2. Provide ConfigurationService as part of a module that can dynamically set CONFIG_URL :

@NgModule({
  providers: [ConfigService],
  imports: [
    HttpClientModule
  ]
})
export class ConfigModule {
  static buildForConfigUrl(configUrl: string): ModuleWithProviders {
    return {
      ngModule: ConfigModule,
      providers: [
        {
          provide: CONFIG_URL,
          useValue: configUrl
        }
      ]
    };
  }
}

3. Import ConfigModule in your feature modules

Now when you have a feature module that is supposed to have its own configuration available, just import ConfigModule using buildForConfigUrl :

@NgModule({
  exports: [
    MyComponent
  ],
  declarations: [
    MyComponent
  ],
  imports: [
    ConfigModule.buildForConfigUrl('https://my-url/my-config.json')
  ]
})
export class FeatureModule {
}

4. Use ConfigService in your components:

@Component({
  selector: 'my-component',
  template: 'I am your new component. My config is: {{ config$ | async | json }}'
})
export class MyComponent implements OnInit{

  config$: Observable<any>;

  constructor(private configService: ConfigService) {
  }

  ngOnInit(): void {
    this.config$ = this.configService.getConfig();
  }

}

With this approach, you nicely decoupled the concerns: Your feature modules don't need to care how the configuration is loaded, but still its components have the configuration available at runtime.

If you want to go one step further, you could even remove the definition of the config URLs from your feature modules and move it to your AppModule centrally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM