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:
Delete
.env.local
ORadd
.env.local
to your.gitignore
file
And that's it.
Skol!
Cover image credit: https://www.doppler.com/
Subscribe to my newsletter
Read articles from Alex Okros directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by