nestjs configuration with dotenv
There are two problems that make the ConfigService
less useful.
First
When no .env
file is present in any environment, readFileSync
in
dotenv.parse(fs.readFileSync(filePath))
will fail:
[Nest] 63403 [ExceptionHandler] path must be a string or Buffer
TypeError: path must be a string or Buffer
at Object.fs.openSync (fs.js:646:18)
at Object.fs.readFileSync (fs.js:551:33)
at new ConfigService (../config/config.service.ts:8:38)
Even if e.g. process.env.API_KEY
is available
this.configService.get('API_KEY')
will not return anything. So the ConfigService
forces you to use a prod.env
file, which dotenv advocates against:
No. We strongly recommend against having a "main" .env file and an "environment" .env file like .env.test. Your config should vary between deploys, and you should not be sharing values between environments.
https://github.com/motdotla/dotenv#should-i-have-multiple-env-files
Second
You have to import the config module and inject the service in order to use it. When you use env variables like this
imports: [
MongooseModule.forRoot(process.env.MONGO_URI, { useNewUrlParser: true }),
ConfigModule,
],
the config service is useless.
Read more about config in the environment here: https://12factor.net/config
But this is not recommended to use .env in production environnement. So how to deploy that way ?
Actually, it is not recommended to commit your .env files. It's perfectly fine to use them in production :-).
Why not use the standard method with dotenv and process.env.PORT?
It allows decoupling your core code from the code responsible for providing configuration data. Thus:
- The core code is easier to test: doing some manual changes/mocking of
process.env
is such - a - pain, whereas mocking a "ConfigService
" is pretty easy - You can imagine using anything else than environment variables in the future by just replacing a single method (or a few getters) in a dedicated class, instead of replacing all the occurrences of
process.env.*
in your code // to be fair, this is unlikely to happen, as using env. variables is the most common way to load configuration data, but still.