简体   繁体   中英

NX + NestJS: Sharing NX environment variables

I read an old thread where it is recommended to share NX environment variables like the following:

import { environment } from '../environments/environment';

@Module({
    providers: [
        {
            provider: 'someProviderName',
            useValue: environment.someEnvironmentValue
        }
    ],
    MyService
})
class AppModule {
}

Then, you access them like:

@Injectable()
class MyService {
    constructor(@Inject('someProviderName') someEnvironmentValue: someType) {
    }
}

The justifications are that:

  1. It keeps your libs env independent.
  2. It allows you to build libs once, without knowing the apps they are used by or the env they ran in.

This is fine if you just need access to the environment variables from AppModule , but how can you share these environment variables with imported library modules? Especially library modules whose source does not reside within the same project as the environment.ts files?

Does every library module that need access to environment variables need to be a dynamic module (as well as all its parent modules) in order to take advantage of environment variables this way? And as such, do you need to chain down forRoot calls to get to any module that needs to access these variables?

Ex:

                            AppModule: DynamicModule
                                    |
                            CoreModule: DynamicModule
                                |           |
     SomeFeatureModule: DynamicModule     SomeOtherFeatureModule: NestModule
  1. AppModule (Needs ENV so it becomes a DynamicModule with ForRoot )
  2. CoreModule (Needs env from AppModule so it becomes a DynamicModule with ForRoot
  3. SomeFeatureModule needs env from CoreModule so it becomes a DynamicModule with forRoot )
  4. ... so on and so forth.

Also what would making all modules that need environment values into DynamicModule do to performance?

Example:

@Module({})
export class MyLibModule {
  static forRoot(providers: Provider[]): DynamicModule {
    return {
      module: MyLibModule ,
      providers: [...providers],
    };
  }
}
const ENV_VALUE_PROVIDERS: ValueProvider[] = [
  {
    provide: 'PRODUCTION',
    useValue: environment.production,
  },
];
@Module({
  providers: ENV_VALUE_PROVIDERS,
  imports: [MyLibModule.register(ENV_VALUE_PROVIDERS)],
})
export class AppModule {}

Why does NestJS force any lib modules to be dynamic to access these type of environment variables in this case given these variables are available at compile-time?

The only other solution I have thought of is to create a Library Module that gets imported by every module that needs environment variables. This module would be initialized in the AppModule using forRoot with the environment variables to be exported. The problem with this solution is that many libraries would then have a direct dependency on this module.

I still don't have the answers to my questions on DynamicModule s, but for the time being I unblocked myself by:

Injecting the environment variables using a ValueProvider in my AppModule , and then using a "factory" option object in the module to pass in the particular environment variable that the module needs.

Here's some untested code illustrating the concept:

providers: [{
  provide: "Environment",
  useValue: environment
}]
MyModule.register({
  provide: 'MY_OPTIONS',
  value: async (environment: any) => environment.MY_VARIABLE,
  inject: ["Environment"],
}),
export class MyModule {
  static register(options: any): DynamicModule {
    ...
    return {
      module: MyModule,
      ...
    };
  }
}

This article goes into good detail on the concept.

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