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:
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
AppModule
(Needs ENV so it becomes a DynamicModule
with ForRoot
) CoreModule
(Needs env from AppModule
so it becomes a DynamicModule
with ForRoot
SomeFeatureModule
needs env from CoreModule
so it becomes a DynamicModule
with forRoot
) 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.