151

I want to use separate .env files for each mode (development, production, etc...). When working on my vue.js projects, I can use files like .env.development or .env.production to get different values for the same env key. (example: in .env.development: FOO=BAR and in .env.production: FOO=BAZ, in development mode process.env.FOO would be BAR, in production i'd be BAZ).

I'm working on an Express server and want to use these same kinds of .env files to store the port, db uri, user, pwd...

I know I can edit the scripts in package.json like this:

"scripts": {
    "start": "NODE_ENV=development PORT=80 node ./bin/www",
    "start-prod": "NODE_ENV=production PORT=81 node ./bin/www"
}

but this gets messy when using multiple variables.

I've tried using dotenv but it seems like you can only use the .env file. Not .env.development and .env.production.

Can I use the dotenv package or do I need another one? Or could I do this without any package at all?

3
  • 3
    Welcome to Stack Overflow. Why would you need multiple environment files on one host? Normally your development and production environments are on different hosts. (dev on your computer and production in the cloud for example). Commented Mar 28, 2019 at 20:18
  • npmjs.com/package/dotenv#should-i-have-multiple-env-files Commented Mar 28, 2019 at 20:24
  • 1
    For reference, here is how Vue CLI lets you use multiple .env files. I think that's what Jonas refers to in the question. I find this way for working with env files very useful. cli.vuejs.org/guide/mode-and-env.html#environment-variables Commented Dec 18, 2020 at 3:55

13 Answers 13

241
+250

You can specify which .env file path to use via the path option with something like this:

require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` })
Sign up to request clarification or add additional context in comments.

10 Comments

For anyone else: i finally went with this: const path = require('path'); require('dotenv').config({ path: path.join(__dirname, ../.env.${process.env.NODE_ENV})});
If I use this solution I seem to need to place this line of code in every javascript file that I want to use the env values... Is there no global way so I can just have one line and all files access the values?
@goldenmaza You can preload them when running your node service in terminal like this. node -r dotenv/config app.js dotenv_config_path=/custom/path/to/your/env/vars. See also here npmjs.com/package/dotenv
NODE_ENV should not be used to set the application environment. A separate environment variable like APP_ENV may be used for this. You may want NODE_ENV to be production in your non production environments as well. nodejs.dev/learn/…
@Arst NODE_ENV and APP_ENV handle separate concerns. NODE_ENV is intended to be understood by Node (and not your application logic) and has only 2 possible values - 'development' and 'production' which Node uses internally to control logging, caching etc. APP_ENV (or any other name) is defined by the application (and so can have any value) and used for application config Eg. connect to 'staging' DB. So you may even want to mix different NODE_ENV and APP_ENV values as per your needs. nodejs.dev/en/learn/…
|
21

For TypeScript / ESM:

import dotenv from 'dotenv'

dotenv.config({ path: `.env.${process.env.NODE_ENV}` })

1 Comment

``` import * as dotenv from 'dotenv'; dotenv.config({ path: .env.${process.env.NODE_ENV} }); ```
15

The above two answers are both slightly off. let me explain. Answer from KyleMit below is missing ./ to indicate current directory.

  • the ./ indicates current directory in Node.js. The Second . prior to env indicates a hidden/private file. Thats why in KyleMits answer if the env file was not in the root of the PC it would never find it. The simplest way to do it in my opinion is to add a ./ this says "hey computer look in my current directory for this file".
//look in my current directory for this  hidden file. 
// List hidden files in dir: ls -a
 
require('dotenv').config({ path: `./.env.${process.env.NODE_ENV}` })


//I reccomend doing a console.log as well to make sure the names match*
console.log(`./.env.${process.env.NODE_ENV}`)

1 Comment

if you dont have a NODE_ENV this will give .env.undefined
7

I'm using the custom-env npm package to handle multiple .env files. Just put this at the top of your code:

require('custom-env').env();

and it will load environment variables from the file .env.X, where X is the value of you NODE_ENV environment variable. For example: .env.test or .env.production.

Here is a nice tutorial on how to use the package.

Comments

5

From answers from above: This is the final result that worked for me.

.env.dev file in src dir.

import path from 'path';

dotenv.config({ path: path.join(__dirname, `./.env.${process.env.NODE_ENV}`)});

Comments

5

This work for me:

File .env

NODE_ENV=dev
DB_HOST=localhost

File .env.dev

DB_HOST=dev-host
DEV_VAR=new-variable

Code

require("dotenv").config();

if (process.env.NODE_ENV === "dev") {
  const result = require("dotenv").config({ path: ".env.dev" });

  process.env = {
    ...process.env,
    ...result.parsed,
  };
}

const dbConfig = {
  host: process.env.DB_HOST,
};

console.log(dbConfig.host);
console.log(process.env.DEV_VAR);

Comments

4

Update:

Note that Node.js has had built-in support for envs after 20.6.0.


Install the dotenv package:

npm install dotenv

We need to get the .env file name based on NODE_ENV, it might be undefined, set default to development:

const envFileName = `.env.${process.env.NODE_ENV || "development"}`

Import the dotenv package and use it:

dotenv.config({ path: envFileName });

Comments

2

You can try: https://www.npmjs.com/package/dotenv-cli, use it like this:

"scripts": {
    "start": "dotenv -e .env.development node ./bin/www",
    "start-prod": "dotenv -e .env.production node ./bin/www"
}

Comments

1

package.json

"scripts": {
    "start-dev": "dotenv_config_path=.env.development nodemon index.js",
    "start-prod": "dotenv_config_path=.env.production nodemon index.js"
  },

Comments

1

If you want to have default environment variables too:

dotenv.config(); // Loads the default .env.
dotenv.config({ path: `.env.${process.env.NODE_ENV}` }); // loads the environment specific .env if any.

Comments

1

Step 1: create a .env.dev file in the root director

Step 2: add this code in ur app.js or db.js

dotenv.config({ path: ['.env.dev', '.env'] }); // for development

dotenv.config(); // for production

Step 3: Restart the Server

I am using Node.js v22.1.0 and Express 4.16.1 and Dotenv ^16.4.5

Comments

0

I wish to publish my own answer to provide additional practical infos.
In the following example I will show a slightly different multi-env handling.

Needed files (it is not a law)

  • .env --> for common variables
  • .env.production --> for production only variables
  • .env.development --> for development only variables

Import the envs

First of all import the common one.

require('dotenv').config({ path: '.env' });

Then import the one that depends on the running mode

require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });

Note
This one will skip eventual variables declared by the previous env import (in our case, the common one).

Where the NODE_ENV comes from?

I personally use the VSC Nodejs debugger functionality, so I needed to setup it too.

package.json

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "NODE_ENV=development nodemon src/server.js",
    "start": "NODE_ENV=production node src/server.js"
  },

launch.json

This piece was generated by VSC by clicking on "create launch.json file" in the Debug section, and then selecting NodeJs.

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "program": "${workspaceFolder}/src/server.js",
            "env": {
                "NODE_ENV": "development"
            }
        }
    ]
}

Hope this helps. Bye.

Comments

-5

The official doc of dotenv does not recommend having multiple .env files.

"Should I have multiple .env files? 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."

10 Comments

DV bc This misinterprets either OP question or the doc: the doc advice is against using multiple .env files in the same environment (eg, loading main.env and test.env in the same process), not blanket advice against having multiple files.
Apologies for DV @rom5jp (I would remove it if I could). I re-read the docs, and it does sound like it doesn't recommend multiple files. However, I suspect this advice was not intended for this context, as it basically negates most of the utility of .env file in the first place (unless you never run multiple environments on your local machine).
In my opinion, the quoted recommendation against multiple .env files is poorly written and it's not clear what they mean. I agree that your config should vary between environments. But that means you will need one env file per environment. I think @FrozenKiwi is right: the recommendation is probably against multiple env files for one particular environment.
I think we've all been confused by the dotenv's wording. They say 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., which seems like it discourages overrides/combinations -- the "AND" is the operative word. I think he majority of us are more curious about different local environments (e.g., .env.development, .env.production, etc) to test code locally w/ different resources.
I also want to highlight their expectations/advice in how the .env is intended to be used. They say It should only include environment-specific values such as database passwords or API keys, which might explain why they don't expect to use a combination of environment files. Per: github.com/motdotla/dotenv#should-i-commit-my-env-file
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.