Environment Variables in a cloud-native React app (without create-react-app)

Charles N
The Startup
Published in
4 min readJun 10, 2020
React + Webpack can solve many bundling problems

Accessing environment variables in Node.js is a straight-forward process: We set the environment variable and we access it on Node’s process.env object. In React.js, APIs and secrets that need to be accessed (maybe in a fetch) are best hidden from the app code.

Environment variables can help us to obscure this data. However, React is served on the browser… which doesn’t include Node. Create-react-app offers a simple way to access environment variables, but what if we have a custom React app built from the ground-up? Accessing environment variables can make us want to Frisbee our machines through the nearest window.

What we’re solving

We want to figure out how to reliably access and use an environment variable from within React.js code, without using create-react-app, in a containerized app.

How we’re solving

  • Declare an environment variable and try to access it in React
  • Access an ‘API’ environment variable by leveraging webpack
  • Containerize the application in Docker and try it out

Setting environment variables

Typically, if we want to set an environment variable, we’d $ export VARIABLE=VALUE. We could also store them in a .env file. As we know, Node gives us the process.env.VARIABLE for access.

Trying to access process.env in React

Let’s say that we want to perform a fetch GET request on a URL that’s stored in an environment variable. Maybe the variable is API=http://localhost:5000. In React, trying to access this variable in the request might look this:

Running that will trigger the .catch because the browser can’t read this environment variable. In React, we’ll need to use webpack to map the OS’s environment variables to webpack’s env variables.

Using webpack to assign environment variables

Let’s assume we’re working with an app that’s mostly set up, given that we’re in this article right now. If webpack isn’t already installed within the Node application, let’s do that: $ npm i --save-dev webpack webpack-cli

Within our package.json file, we can access the scripts key containing npm scripts that run CLI commands.

We can use the webpack CLI to write a command that starts our React app. Within this command, we can add an --env option which will add webpack placeholders for these variables. It might look something like this:

webpack --env.API=http://localhost:5000 --config webpack.config.js --watch

Before this command does anything useful for us, we need to understand that this env.API webpack env variable won’t be compiled to the actual OS environment variable value. This is because webpack needs us to explicitly tell it to. We can do that in webpack.config.js

Building the webpack config:

We’re going to use webpack’s DefinePlugin to map webpack’s CLI-defined variables to the system’s environment variables:

This is an entire config. You might not have one yet, or your config may look different, but the important points are:

  • module.exports is now a function that accepts the env argument
  • We have a helper envs that maps environment variables to webpack’s env variables.
  • The returned config has a plugins key with our new DefinePlugin(envs)

Accessing our set environment variables

Now that webpack is configured to look for environment variables on process.env and assign them to the variables we include in the --env option with the CLI script, we can access them in React.

Let’s go back to our API environment variable. We can set $ export API=http://localhost:5000. In package.json at the scripts key, we‘ll replace our webpack start script value with

webpack --env.API=$API --config webpack.config.js --watch

Now webpack’s variable is mapped to the OS environment variable. So going back to our fetch GET request on process.env.API base URL:

We’ll pass into the .then and successfully log the data on the other end of the route, if that’s the route that exists on our supposed API. Now we can access environment variables from React!

Accessing environment variables in a container

Now that we’ve gained access to process.env from React, we can write a Dockerfile to build an image from. When we run the image as a container, we can use the Docker CLI for running the image to include environment variables we want set in its OS.

I’m again going to make the wild assumption that you have a server to put React on the browser with. Let’s say our Dockerfile in the root of our app looks something like this, then:

So we run a build command with the Docker CLI, maybe:

docker build -t example:1.0.0 .

Now that we have an image to run, we can pass it the API environment variable:

docker run -p 3000:3000 --env API=http://localhost:5000 example:1.0.0

Now, if we have an API backend running on localhost:5000 and we open up localhost:3000, where we are running our containerized React app, the console will be logging the response object that we told it to in our fetch!

Some prefer to use a .env file, but I find that in a cloud-native microservice architecture, it’s sometimes best to keep the application ignorant of the environment variables that it accesses.

Congrats! Thanks! And please comment anything missed!

--

--