loading...
Cover image for Managing .env variables for provisional builds with Create React App
Jam3

Managing .env variables for provisional builds with Create React App

donghyukjacobjang profile image Donghyuk (Jacob) Jang Updated on ・3 min read

When developing web applications by using Create React App, developers get NODE_ENV=development on their local environment and NODE_ENV=production on the production build by default. And, modifying NODE_ENV is forbidden. According to the Create React App, this is an intentional setting to protect the production environment from a mistake/accident deploying.

You will be able to see scripts like below in package.json after creating your web app.

// package.json
scripts: {
  "start": "react-scripts start", // `NODE_ENV` is equal to `development`.
  "build": "react-scripts build", // `NODE_ENV` is equal to `production`.
  ...
}

If you create or already have .env.development and .env.production in the root of your project, these files will be used for running each script. npm start will pick up .env.development, and npm build will use environment variables in .env.production.

-
What if you want to setup .env.staging?

This article will show you how to manage environment variables for provisional builds.

Let's dive into that! Oh, if you do not have any experiences of CRA, please Getting started

-

Story

Imagine that your project will have three separated provisional environments; development, staging, and production. Each environment is using different API endpoints. In addition to that, the project may require a REACT_APP_CUSTOM_NODE_ENV. This is because NODE_ENV will always be production for the build regardless.

-

Goal

  • Create .env.development, .env.staging, and .env.production.
  • Configure environment viriables for each build.
  • Modify scripts in package.json

-

Getting started

Step 1.

Thankfully, dotenv comes out of box. Let's create .env files under the root folder to manage environment variables. The files are .env, .env.development, .env.staging, and .env.production.

  • .env - Keep all common/shared environment variable
  • .env.development - Variables are used for the local development
  • .env.staging - Variables are used for the staging build
  • .env.production - Variables are used for the production build

For example;

#.env
REACT_APP_DOC_TITLE = "Document title"
//.env.developement
REACT_APP_API_ENDPOINT = "https://development-api.endpoint.com/"
#.env.staging

# NODE_ENV will always be set to "production" for a build
# more details at https://create-react-app.dev/docs/deployment/#customizing-environment-variables-for-arbitrary-build-environments
REACT_APP_CUSTOM_NODE_ENV = "staging"
REACT_APP_API_ENDPOINT = "https://staging-api.endpoint.com/"
#.env.production
REACT_APP_API_ENDPOINT = "https://api.endpoint.com/"

NOTE: The prefix REACT_APP_ is required when creating custom environment variables.

.env.development and .env.production

As a default behavior, those files will be served with no configuration. You do not even have to update scripts in package.json

.env.staging

Here is the main focus of this post. To target .env.staging file for the staging build, we need a library to achieve this.

1- Let's install env-cmd. This library will will help us on using/executing a selected environment file. See more detail

// execute command below at the root of project
$ npm install env-cmd --save
or
$ yarn add env-cmd

2- Add a script in package.json like below.

// package.json
scripts: {
  "start": "react-scripts start", // `NODE_ENV` is equal to `development`.
  "build": "react-scripts build", // `NODE_ENV` is equal to `production`.
  "build:staging": "env-cmd -f .env.staging react-scripts build", // `NODE_ENV` is equal to `production`.
  ...
}

3- Finally, test your build:staging script.

-

Conclusion

The intention of this technique is to use different custom environment variables for many provisional environments without ejecting the default CRA configs.

-

Resources

Special Thanks

  • @foxbit19 - found env-cmd version 8.x requries additional argument to link to the custom env file.
  • @j6000 - pointed out NODE_ENV for the build will always be set to "production" regardless.

Posted on by:

Jam3

Jam3 is a design and experience agency that partners with forward thinking brands from around the world.

Discussion

markdown guide
 

How to run it?

i make env.local

it contains

CUSTOM_NODE_ENV="local"
REACT_APP_MAIN_SERVER_API=http://192.168.1.11/api/v1/

this run script in npm

"start:local": "env-cmd -f .env.local react-script start"

when i run

npm start local

it fails and load to .env

 

@consciousnessdev Thanks for your comment.

You should add REACT_APP_ prefix to your all custom env variables. eg, REACT_APP_CUSTOM_NODE_ENV.

the command is npm run start:local according to your scripts, just missing :.

Sorry for making this mistake, and I will update the article.

Again, thanks for your patient.

Best,
Donghyuk (Jacob) Jang

 

[Update] But when i run it with your suggestion, it still have an error

npm run start:local

> apps@0.1.0 start:local /home/me/react/apps
> env-cmd -f .env.local react-script start

spawn react-script ENOENT
Hangup
npm ERR! code ELIFECYCLE
npm ERR! errno 129
npm ERR! apps@0.1.0 start:local: `env-cmd -f .env.local react-script start`
npm ERR! Exit status 129
npm ERR! 
npm ERR! Failed at the apps@0.1.0 start:local script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/me/.npm/_logs/2019-12-04T01_34_08_907Z-debug.log

I have tried in the example repository, and it seems to be working fine. You may have some conflicts.

The example repository is github.com/DonghyukJacobJang/cra-e...

You will be able to find .env.local and start:local in package.json.

Since I cannot see all your config and settings, providing you the example repo is the best thing I can do at the moment.

Please let me know if you have questions.

Best,
Donghyuk (Jacob) Jang

Pardon Me, i'd typo on 'react-script', which is true 'react-scripts', with 's' in the end of script it, thanks a lot! :O

 

Thanks Donghyuk. One thing to note here is that, while my .env.staging is loaded, process.env.NODE_ENV is set to production despite the NODE_ENV=staging setting in .env.staging

Is this consistent with your experience?

 

Seems so based on create-react-app.dev/docs:

Variables in .env.production will be used as fallback because NODE_ENV will always be set to production for a build.

Assuming true, what's the value in adding NODE_ENV=staging to .env.staging?

 

I will test this out ASAP, but I remember that I had to create a custom var to distinguish environments in javascript code.

 
 

It's a great post! Thank you. I needed this.

 

I am very glad that it helps you :) Thank you so much for your message.

 

I think, env-cmd should be installed by
$ yarn add -D env-cmd

 

I am using visual studio 2017 with React template
in which I followed above steps but its not working for staging

can you add working source code also

 

There was env-cmd version update and it required a parameter to point a custom env file, As @foxbit19 discovered.
CRA template with env-cmd example is available at github.com/DonghyukJacobJang/cra-e... .
Thank you so much @sushantraje2000

 

Thanks for your article! I think env-cmd needs -f argument to load the custom file correctly. Otherwise it fails and load .env file by default.

 

Thanks for this information. When this article was written, it was using env-cmd version 8.0.2. It was not required -f option. I also just tested the latest version which is 9.0.3 without the parameter and caused an issue. As a result, when pointing a custom env file, it is required. Thank you so much @foxbit19 .

 

By far the simplest solution. Good stuff!

 

Thank you for the article!

I was initially confused as I was not aware that "start" and "build" scripts use ".env.development" and ".env.production", respectively, by default.

 
 

Will it apply with the yarn build command?