Using environment variables in a React application

  • Build time variables: these are variables that are provided when the application is compiled (typically when npm run build is executed). In our example, we’ll pass to the application the git hash of the code when it was built, and an additional arbitrary value.
  • Run time variables: these variables are provided when the application runs, usually these variables differ depending on the environments (development, staging or production). In our example we’ll pass an API URL from the server to the front end application.

Skipping ahead

Build Time Variables

Using a .env file

const { REACT_APP_MY_ENV } = process.env;
$ npm i dotenv
// package.json"scripts": {
"start": "node -r dotenv/config src/index.js"

Using temporary environment variables

// package.json"scripts": {
"start": "REACT_APP_GIT_HASH=\"$(git rev-parse HEAD)\" react-scripts start"
const { REACT_APP_GIT_HASH } = process.env;console.log(`Version ${REACT_APP_GIT_HASH}`);
// Version 8e8bd178bd91adb33b7eb5cb1b8220a079a87e65
function MyComponent() {
return <div>{ REACT_APP_GIT_HASH }</div>; // renders the hash
$ npm run build
$ serve -s build
// App.js
const { REACT_APP_GIT_HASH, REACT_APP_MY_ENV } = process.env;
console.log(REACT_APP_GIT_HASH); // 8e8bd178bd91adb3.....
console.log(REACT_APP_MY_ENV); // Some value
function App() {
return (
<div>Git Hash: {REACT_APP_GIT_HASH}</div>
<div>My Env: {REACT_APP_MY_ENV}</div>
  • Prefix the variable name with REACT_APP_
  • The value can be provided it on the command line
    "REACT_APP_MY_VAR=foo react-scripts start"
  • The value can be provided in a .env file
  • Read it from process.env
    const { REACT_APP_MY_VAR, REACT_APP_OTHER_VAR } = process.env;
  • No sensitive information

Runtime Variables

// .env
const { REACT_APP_API_URL } = process.env;
// public/index.html<body>  //...

window.API_URL = "\<\%= API_URL \%\>";
// backend/index.jsconst express = require('express');
const path = require('path');
const app = express();
const port = 4000;
// where ever the built package is
const buildFolder = '../frontend/build';
// load the value in the server
const { API_URL } = process.env;
// treat the index.html as a template and substitute the value
// at runtime
app.set('views', path.join(__dirname, buildFolder));
app.engine('html', require('ejs').renderFile);
express.static(path.join(__dirname, `${buildFolder}/static`)),
app.get('/', function(req, res) {
res.render('index.html', { API_URL });
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
// App.jsconst API_URL = NODE_ENV === 'development' ? process.env.REACT_APP_API_URL : window.API_URL;
$ cd frontend
$ npm start
$ open http://localhost:3000
Screenshot of home page in development
$ npm run build
$ cd ../backend
$ npm start
$ open http://localhost:4000
Screenshot of home page in production
  • If the file is a ‘config file’ containing constants not likely to change from one server to another or from one build to the next (like a timezone, a locale or specific content, like the site name), then it’s OK to check it in.
  • If the file contains application configuration, like a database password, an API key, any value that needs to change without having to rebuild the application or from server to server, then it’s better not to check it in and use environment variables. Check the dotenv config on how to manage multiple env files.




Previously Paris and Geneva, currently New York. Can also be found at

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

CSS In JS? Yes! Styled Components 💅🏽

Tricky Questions Faced

Understanding Hooks in React

ReactJS Pinterest Clone

Set up Firebase in Your Angular App for the First Time

JavaScript: Learn ‘this’ - Oh, so ‘this’ is this!!

NextJS, Express, Typescript, etc. in a monorepo setup

RxJS based state management in Angular — Part I

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Arnaud Dostes

Arnaud Dostes

Previously Paris and Geneva, currently New York. Can also be found at

More from Medium

How does Express rate limit works?

How to Set Up a Node.js Project with TypeScript

Template Engine (Ejs vs Pug )

Sharp Notes to SQL Users Migrating to DynamoDB