How to load custom process environment .ENV variables in webpack with craco (Create React App Configuration Override)

How to load custom process environment .ENV variables in webpack with   craco (Create React App Configuration Override)

When you're using craco, and you need to specify different .env files with different .env variables, you'll need to override some webpack configs.

We'll be using 4 .env files:

.env.local
.env.development
.env.staging
.env.production

We'll then open craco.config.js from our project root and add the following:

const DotEnv = require('dotenv');
const webpack = require('webpack');


const ENV = process.env.DEPLOY_ENV || 'dev';
const result = DotEnv.config({ path: `./.env.${ENV}` });

if (result.error) {
  throw result.error;
}

const env = DotEnv.config({ path: `./.env.${ENV}` }).parsed;
const envLocal = DotEnv.config({ path: './.env.local' }).parsed || {};

// collect all .env keys and values
const envKeys = Object.keys(env).reduce((prev, next) => {
  // first we search for each key inside of .env.local, because of precedence
  prev[`process.env.${next.trim()}`] = (envLocal[next]) ? JSON.stringify(envLocal[next].trim()) : JSON.stringify(env[next].trim());

  return prev;
}, {});

// check things out
console.log(`
  key: ${ENV.toLocaleUpperCase()},
  value: ${process.env.REACT_APP_DEPLOY_ENV},
  accumulator: ${envKeys}
`);

// feed them keys to your brand new custom webpack configuration
module.exports = {
  webpack: {
    plugins: [
      new webpack.DefinePlugin(envKeys),
    ],
  },
};

To break things up:

Install dotenv npm packages if you haven't already:

npm install dotenv --save-dev

Open craco.config.js and import dotenv and webpack packages:

const DotEnv = require('dotenv');
const webpack = require('webpack');

Add a REACT_APP_DEPLOY_ENV (or however you want to call it) variable in all your .env files:

REACT_APP_DEPLOY_ENV='local' // this is for .env.local
REACT_APP_DEPLOY_ENV='dev' // this is for .env.development
REACT_APP_DEPLOY_ENV='stg' // this is for .env.staging
REACT_APP_DEPLOY_ENV='prd' // this is for .env.production

Load up your REACT_APP_DEPLOY_ENV and check for the .env file depending on the dev medium you're on, with the help of the dotenv package:

// load .env files based on your present medium you're on
const ENV = process.env.DEPLOY_ENV || 'dev';
const result = DotEnv.config({ path: `./.env.${ENV}` });

// if there's no file, throw an error
if (result.error) {
  throw result.error;
}

Load up your .env and .env.local (this should have precedence because different developers work on different files) in JSON format:

const env = DotEnv.config({ path: `./.env.${ENV}` }).parsed;
const envLocal = DotEnv.config({ path: './.env.local' }).parsed || {};

Accumulate all those keys with the help of a reducer:

const envKeys = Object.keys(env).reduce((prev, next) => {
  // .env.local variables have priority over other .env files
  prev[`process.env.${next.trim()}`] = (envLocal[next]) ? JSON.stringify(envLocal[next].trim()) : JSON.stringify(env[next].trim());

  return prev;
}, {});

And finally feed them to the webpack configuration:

module.exports = {
  eslint: {
    enable: true,
  },
  webpack: {
    plugins: [
      new webpack.DefinePlugin(envKeys),
    ],
  },
};

Just make sure, before you commit and push, to:

  1. Delete .env.local OR

  2. add .env.local to your .gitignore file

And that's it.

Skol!

Cover image credit: https://www.doppler.com/

Did you find this article valuable?

Support Ravioli Code by becoming a sponsor. Any amount is appreciated!