Photo by Emile Perron on Unsplash

Environment Variables in Client-Side

Ashkan Ahrabi
Webtips
Published in
6 min readJun 26, 2020

--

Most of us, Front-End/React Developers, are not aware of Environment Variable usages in our Client-Side projects. You say “I don’t even know what the heck are they?”, so let’s begin this to be more of a developer :)

In this article you may read:

- What is an Environment Variable

- How it can solve a big problem in scaled front-end projects

- Custom Environment Variables in create-react-app and their most important usage there

What is an Environment Variable?

Environment Variable, as it’s clearly obvious, is a variable that can have a value, but its value is stored outside our project, in the environment the project is running. This environment can be an OS, Server or any Micro Service.

Usages

  • Configuration of the application (HTTP Port and address which the project is being served through)
  • location of static files
  • Endpoints of other external services
  • storage connection information (Database name, …)

The most common problem in scaled Front-End projects

As we’re working on a scaled project in a scaled company, it is kind of weird to have every single API call containing the server Endpoint!
If you don’t follow any architecture in your project, Environment Variables may help you here.

Now imagine there are two different servers to connect. A Staging Server for development and test purposes, and a Production Server which is the server that real users are connected to it. Oops… It’s hard to handle? Don’t worry!

Environment Variables in create-react-app

Most React Developers are using create-react-app for their projects these days. Create-react-app itself has some default environment variables for some configuration of the React project.
The most known environment variable in create-react-app is NODE_ENV.

NODE_ENV has three different values in order to separate Production, Development and Test environments.

  • on npm start, the value of NODE_ENV is “development”
  • on npm test, this value is “test”
  • and finally on npm run build, this value is “production”

Remember that the value of an Environment Variable is always string.

NODE_ENV is not overridable manually. This is to prevent any changes of the Production and Development environments by mistake.

So as we read above, we can enable/disable some parts of our project based on the environment we’re running it.

But this is not completely what we need. Consider we need to run npm start in production environment. Or we need to publish the staging build of our project. Here we can try some custom Environment Variables within create-react-app.

Custom Environment Variables in create-react-app

We can have some custom environment variables to config our application the way we want (defining different Staging and Production Endpoints and …).

We need a .env file to write our Environment Variables in it. We put it next to the package.json in project’s root folder.

├── README.md
├── node_modules
├── package.json
├── .env
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js

Now inside this .env file, we can write custom Environment Variables.

Please note that custom Environment Variables Must have REACT_APP_ as their prefix. Any other environment variables without this prefix, may be ignored in create-react-app.

REACT_APP_API_ENDPOINT = https://api.test.com

Also note that values (which are strings) don’t require quotation marks, unless there’s a space in the string.

How to use these Environment Variables inside React

Variables inside this .env file, are accessible via process.env Object in JS, which is a global object provided by the environment you are working on, through NodeJs.

Remember that, as long as there’s no NodeJs in the browser, here comes the WebPack or other Js Bundlers to handle this.

Now let’s see how we can access an Environment Variable in our React project. Consider that we use axios for sending HTTP requests:

let serverURL = process.env.REACT_APP_API_ENDPOINT;
axios.get(serverURL)
.then(function (response) {
// handle success
})
.catch(function (error) {
// handle error
});

And after building the project, the bundler will replace the first line with the following line:

let serverURL = "https://api.test.com";

So we’re halfway through separating staging and production endpoints in the project. Cause now the API Call is not dependent on a specific URL.

Separating Staging and Production Endpoints without separating the code base

Now that we’ve learnt how to use Environment Variables in React, let’s see how we can have different endpoints/configs in different environments like staging and production.

To do this, we need another .env file for new configs. So let’s have proper names for our .env files:

  • .env.production for production configs
  • .env.staging for staging configs
#This is .env.production fileREACT_APP_ENVIRONMENT = production
REACT_APP_REST_ENDPOINT = https://api-production.test.com
REACT_APP_SOCKET_ENDPOINT = https://socket-production.test.com

Comments are followed by a # in .env files.

#This is .env.staging fileREACT_APP_ENVIRONMENT = staging
REACT_APP_REST_ENDPOINT = https://api-staging.test.com
REACT_APP_SOCKET_ENDPOINT = https://socket-staging.test.com

As we see, variable names are the same in both files. And only the values of the same variable is different. So this may help our React app be free of if statements while sending the HTTP Request.

Now we have to tell our node server, to read one of these two files while it wants to start the project.

Run npm start based on the Environment

For this purpose, we need a npm package called env-cmd which tells our react scripts to start the project with the staging or the production config.

After installing env-cmd, we need to change the react scripts in the package.json file:

"scripts": {
"start:staging": "env-cmd .env.staging react-scripts start",
"start:production": "env-cmd .env.production react-scripts start",
"build:staging": "env-cmd .env.staging react-scripts build",
"build:production": "env-cmd .env.production react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}

And for starting the project, we should run npm run start:staging and npm run start:production instead of the old command npm start .

Dos and Don’ts

  • It’s better not to store .env files in source controls cause it may cause your configs/endpoints being leaked in open source projects.
    But to avoid misunderstandings, you may publish a .env.sample file including variable names with a description of what it is used for:
#This is .env.sample fileREACT_APP_ENVIRONMENT = "staging or production"
REACT_APP_REST_ENDPOINT = "Your Rest Endpoint will come here"
REACT_APP_SOCKET_ENDPOINT = "Your Socket Endpoint will come here"
#You should have 2 different files, .env.production and .env.staging
#with the same variables and different values
  • Always remember to check the Environment Variable and its value, cause if the React application can’t find the true Environment Variable, it won’t affect the application’s starting process and you may face a run-time error.
  • Also changing any Environment Variable needs the node server to being restarted in order to consider the new value.
  • Please note that while create-react-app is bundling your application, there are no Environment Variables in the build folder.
    This is because all of them are replaced with their values. So it is NOT safe to store secret values in Environment Variables with Front-End Web Development. (Although this is common for Back-End developers to store API Keys there).
    If you want to do so, you may have SSR with your React Application, so that Environment Variables are being replaced real-time while application is running. More info here.
  • As it’s referenced, it’s a good idea to ignore some part of your application that is not needed in a specific environment. For example you can ignore Analytics Methods in the staging Environment:
if (process.env.REACT_APP_ENVIRONMENT !== 'production') {
analytics.disable();
}

This may lead to smaller bundle size after building your application.

So as we saw earlier, using Environment Variables could be useful in order to prevent endpoints being exposed, run the entire application in different Environments (e.g Staging and Production) without the pain of switching between different branches and also build the project based on an environment.

Hope you start using them asap. Let me know of any questions or further information in the comments.

Happy Enving :D

--

--