Skip to content

Javascript .env🔗

Load javascript environment variables from .env files using dotenv.

Installation🔗

1
2
3
4
5
# with npm
npm install dotenv

# or with Yarn
yarn add dotenv

Usage🔗

Load a specific file and its env vars as actual Node process env vars (in process.env):

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

The following allows to load multiple env files according to an ENV_FILE and APP_RUNTIME_ENV env var, and will filter out the env vars you'd like to expose to your app to the one defined in the env files (excluding other process env vars):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const DotEnv = require('dotenv');

const dotenvFilesBasePath = './'
// Load env vars from .env.* files in process
const envVarsKeys = [
  process.env.ENV_FILE,
  `.env.${process.env.APP_RUNTIME_ENV}.local`,
  `.env.${process.env.APP_RUNTIME_ENV}`,
  '.env.local',
  '.env',
].filter(Boolean).reduce((keys, path) => {
  if (require('fs').existsSync(dotenvFilesBasePath + path)) {
    const parsedConfig = DotEnv.config({ path: dotenvFilesBasePath + path });

    keys.push(...Object.keys(parsedConfig.parsed));
  }

  return keys;
}, ['NODE_ENV']);

// Filter out allowed env vars (those defined in the .env files)
const envVars = Object.fromEntries(Object.entries(process.env)
  .filter(([key]) => envVarsKeys.includes(key))
  // Optionnaly, exclude some built-time specific vars used for Webpack (prefixed with WEBPACK_):
  .filter(([key]) => !key.startsWith('WEBPACK_'))
);

Note

Adapt the dotenvFilesBasetPath for your env files according to your project. For instance, in a Symfony Webpack Encore projet, your frontend dedicated .env files might be located inside assets/.

Env vars are then loaded in the following order:

  1. .env
  2. .env.local
  3. .env.{production,staging,development}
  4. .env.{production,staging,development}.local

Access vars in your application🔗

In previous versions of Webpack, we used to expose the process.env object directly to our frontend applications.
It used to work because Webpack 4 was included polyfills for some Node.js variables in the browser.
But as of Webpack 5, it's now unavailable by default.

webpack 5 does no longer include a polyfill for this Node.js variable. Avoid using it in the frontend code.

Want to use environment variables with process.env.VARIABLE? Consider using VARIABLE instead. process.env is Node.js specific and should be avoided in frontend code.

However, you can make these variables accessible to your web application using an AppConfig object and the Webpack DefinePlugin plugin.

Using Webpack🔗

In your webpack.config.js:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
const { DefinePlugin } = require('webpack');

module.exports = (env, argv) => {
  return {
    // […]
    plugins: [
      // […]
      new DefinePlugin({
        AppConfig: JSON.stringify({
          NODE_ENV: argv.mode, // default NODE_ENV value to mode value if not provided explicitly through env
          ...envVars, // allowed env vars from env files or their actual process value if provided during build
        }),
      }),
    ],
    // […]
  };
}

In your Makefile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## Build assets
build: export APP_RUNTIME_ENV ?= development
build:
    npx webpack --mode=development

## Build assets in staging mode
build@staging: export APP_RUNTIME_ENV ?= staging
build@staging:
    npx webpack --mode=production

## Build assets in production mode
build@production: export APP_RUNTIME_ENV ?= production
build@production:
    npx webpack --mode=production

Using Webpack Encore🔗

In your webpack.config.js:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var Encore = require('@symfony/webpack-encore');
var webpack = require('webpack');

Encore
  .configureDefinePlugin(options => ({
    AppConfig: JSON.stringify({
      NODE_ENV: process.env.NODE_ENV || 'development', // default NODE_ENV value if not provided explicitly through env
      ...envVars, // allowed env vars from env files or their actual process value if provided during build
    })
  }));

In your Makefile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## Build assets
build: export APP_RUNTIME_ENV ?= development
build:
    npx encore dev

## Build assets in staging mode
build@staging: export APP_RUNTIME_ENV ?= staging
build@staging:
    npx encore production

## Build assets in production mode
build@production: export APP_RUNTIME_ENV ?= production
build@production:
    npx encore production

Define🔗

Define global env vars go to the .env file, and specific development/production/staging env vars to .env.development, .env.production and .env.staging files.

Tip

You could also load a specific .env.local file (or any other file) using ENV_FILE=.env.local make build

Use your variables🔗

On your frontend app, access the variables using the AppConfig global:

1
new ApiClient(AppConfig.API_BASE_URI);

If you're using ESlint, add this variable to your .eslintrc.json allowed globals:

1
2
3
4
5
{
    "globals": {
      "AppConfig": true
    }
}

Last update: December 20, 2024