Node JS environment variables and Heroku deployment

I experienced the same issue with a local NodeJS setup and environment variables and a deployment to Heroku.

My solution was to create a config file which would handle both situations, and give me a tidy, automated approach in my project.

My NodeJS server is run using babel-node, so my config file is written in ES6, you may need to convert that for your own needs.

If we take an example .env file:

NODE_ENV=development
API_ENDPOINT=http://localhost:7000
SOMETHING_ELSE=some-text

And my config.js in the root of the NodeJS app:

import dotenv from 'dotenv';

const result = dotenv.config();
const envs = result.parsed;

module.exports = envs;

You can see in my code, that I use DotEnv and create a envs variable: let envs. Locally I use DotEnv to parse my .env file and pass this through to my application as an object.

This means I can import my variables from my .env in my app easily:

import { NODE_ENV } from './config';

Heroku

In Heroku, you set your env variables in the settings page on the project in the Heroku dashboard. So to avoid committing your .env as fixed vars in your repo (which you should never do), you can access the process.env global variable in the same config file.

So you config.js file becomes:

import dotenv from 'dotenv';
import _ from 'lodash';

const result = dotenv.config();

let envs;

if (!('error' in result)) {
  envs = result.parsed;
} else {
  envs = {};
  _.each(process.env, (value, key) => envs[key] = value);
}

module.exports = envs;

As I already had lodash available in my project, I used this to handle looping through the process.env variable.

Note: This makes every env variable in your dyno available, not just the variables you have set in the Heroku dashboard. You may decide you want to prefix your env's and filter the process.env loop to just the vars you want to expose to your application.

As you can see in my new config file, if there is no error when DotEnv runs, then we can assume that a .env file exists and use the vars from that and set them as we were doing before.

But, if there is an error, then we make the assumption that there is not a .env file, and fall back to checking process.env We then set envs var to be an object envs = {}; and then set each variable we find in process.env as a key value pair. Then export envs as normal.

This makes the env variables from Heroku available in your application, without need to change your logic throughout your application.

Hope this helps anyone who has the same issue.


Today i stumbled upon this problem, i tried several solutions but none worked. My App was working locally but in production mode (heroku) it was not loading process.env correctly.

then i found this https://www.npmjs.com/package/dotenv-webpack

plugins: [
    new Dotenv({ systemvars: true }),
],

Just setting systemvars to true does the trick.. For now I have tested this using different keys for the .env file and the heroku dashboard; They are not connected, and they replace themself correctly in production or dev mode.

Use the package "dotenv-webpack" instead of "dotenv".

I hope this saves some time to anyone facing the same problem


Do not commit your .env to git (i.e. it should be in your .gitignore).

You define env vars on Heroku either via your Heroku dashboard, or with heroku config:set, e.g.

heroku config:set CONVERSATION_USERNAME=Alex

See here for more information.