Dynamically Configuring Microservice Bootstrap
During setting up microservice in nestjs, I faced a challenge. By convention, and as illustrated in nestjs documentation, microservice is boostrapped using following convention.
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
options: {
url: 'xxx.url.com',
protoPackage: 'some/hard/coded/path',
}
},
);
await app.listen();
}
bootstrap();
The above configuration, however, is static. Therefore, it includes hard coding, such as the port/url, transport method, etc.
I wanted to make the microservice configuration using .env
variables, using ConfigService
offered by @nestjs/config
.
Therefore, I had to find a way to somehow import config module within the provided code, but it was difficult. From my research, I found an nestjs open discussion that illustrates the problem (link (opens in a new tab)).
I then decided to define an ApplicationConetext
, and use configService
that gets the ConfigService
provider in my AppModule
.
From the configSerivce
, I defined my microserviceOptions
. With these, I then created the actual app
, and closed the temporary appContext
.
Note that inorder to achieve this, my AppModule
must import ConfigModule
.
async function bootstrap() {
const appContext = await NestFactory.createApplicationContext(AppModule);
const configService = appContext.get(ConfigService);
const url = configService.get<string>('MICROSERVICE_APP_URL');
const microserviceOptions: MicroserviceOptions = {
transport: Transport.GRPC,
options: {
url,
protoPath: join(__dirname, '../app.proto'),
package: APP_PACKAGE_NAME,
},
};
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AuthModule,
microserviceOptions,
);
appContext.close();
await app.listen();
}
bootstrap();