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.