react

Setting Multiple Environment Variables in React

Nov 14th, 2020Abhishek EH2 Min Read

You might have come across instances where you would want to use a certain value in the development environment and another value in the production environment, say for instance there is an API endpoint from which you fetch a list of users. Now definitely you will have a different URL for each of the environments, such that development data is not fetched in production.

To identify which environment we are in, we can make use of a special environment variable: process.env.NODE_ENV. When you are using Create React App, the react-scripts will set the value of NODE_ENV to development when npm start is executed and to production when you run npm run build.

So you can make use of NODE_ENV to determine which environment you are in and set the value of API endpoint accordingly as shown in the below code snippet

1let API_ENDPOINT
2if (process.env.NODE_ENV === "production") {
3 API_ENDPOINT = "https://example.com"
4} else {
5 API_ENDPOINT = "https://dev.example.com"
6}

However, the problem with the above approach would be that we will have to put this check wherever we would want to use the environment-specific values and if we would want to add an environment or change value for a particular environment, we will have to scan through the whole codebase, which is a cumbersome task.

To solve this problem, React ships with .env file support. That is, we can have a file named .env at the root directory of our project and have the values defined there. Let's see how we can implement it in the next steps.

Project Setup

First of all, let's create a new react project using the below command:

1npx create-react-app environment-variables

Now in the root directory create 3 files .env, .env.development and .env.production with the following content:

.env
1REACT_APP_API_ENDPOINT = https://default.example.com
.env.development
1REACT_APP_API_ENDPOINT = https://dev.example.com
.env.production
1REACT_APP_API_ENDPOINT = https://example.com

Update App.js with the following code:

App.js
1function App() {
2 console.log({ REACT_APP_API_ENDPOINT: process.env.REACT_APP_API_ENDPOINT })
3 return <div>Home</div>
4}
5
6export default App

In the above code, we are logging the value of process.env.REACT_APP_API_ENDPOINT, which means any value stored inside .env files can be accessed via process.env.

Create React App requires all the environment variables to begin with REACT_APP_, any other variables will be ignored. This is done to avoid developers from accidentally committing any environment variables that may contain app secrets.

Now let's start the application using npm start and see what is logged in the browser console:

Endpoint Log start

From this, we can understand that whenever npm start is run, NODE_ENV will be set to development and environment variables will be fetched from .env.development

Now let's build the application using npm run build and try running the application using the below command:

1serve -s build

If you don't have serve installed globally, please do so by running npm i -g serve

If you open https://localhost:5000, you will see that endpoint is fetched from .env.production and logged. Endpoint Log build

CRA Documentation says that you cannot override NODE_ENV manually. So if you want to have 2 more environments, say qa and staging then you cannot override NODE_ENV and expect it to work.

Having multiple environments

To support multiple environments, we need to install an additional library and modify the build scripts slightly. Let's install env-cmd, as a development dependency using the following command.

1npm i -D env-cmd

env-cmd helps in specifying which particular .env file to consider while building the application.

So now let's add .env files for qa and staging environments:

.env.qa
1REACT_APP_API_ENDPOINT = https://qa.example.com
.env.staging
1REACT_APP_API_ENDPOINT = https://stage.example.com

And add couple of build scripts to package.json

package.json
1{
2 // ...
3 "scripts": {
4 "start": "react-scripts start",
5 "build": "react-scripts build",
6 "build:qa": "env-cmd -f .env.qa npm run-script build",
7 "build:staging": "env-cmd -f .env.staging npm run-script build",
8 "test": "react-scripts test",
9 "eject": "react-scripts eject"
10 }
11
12 // ...
13}

So now if you run npm run build:qa or npm run build:staging, and serve the application, you will see the respective endpoint URL being logged.

Endpoint Log qa Endpoint Log staging

Keeping all the configuration in one file

If you don't like having a separate file for each environment, you can store all the configurations in one file!

Create a file named .env-cmdrc in the root directory of the project with the following content:

.env-cmdrc
1{
2 "development": {
3 "REACT_APP_API_ENDPOINT": "https://devapi.example.com"
4 },
5 "qa": {
6 "REACT_APP_API_ENDPOINT": "https://qaapi.example.com"
7 },
8 "staging": {
9 "REACT_APP_API_ENDPOINT": "https://stagingapi.example.com"
10 },
11 "production": {
12 "REACT_APP_API_ENDPOINT": "https://prodapi.example.com"
13 }
14}

Now add few scripts to package.json to read the variables from the above file:

package.json
1{
2 //...
3 "scripts": {
4 "start": "react-scripts start",
5 "build": "react-scripts build",
6 "build:dev": "env-cmd -f .env.development npm run-script build",
7 "build:qa": "env-cmd -f .env.qa npm run-script build",
8 "build:staging": "env-cmd -f .env.staging npm run-script build",
9 "build-dev": "env-cmd -e development npm run-script build",
10 "build-qa": "env-cmd -e qa npm run-script build",
11 "build-staging": "env-cmd -e staging npm run-script build",
12 "build-prod": "env-cmd -e production npm run-script build",
13 "test": "react-scripts test",
14 "eject": "react-scripts eject"
15 }
16 //...
17}

Now build the development code using the command npm run build-dev, run the built code using serve -s build, and you will see the correct API URL being printed:

Endpoint Log dev

Source code

You can view the complete source code here.

Leave a Comment

© 2020 CodingDeft.Com