Injecting Environment Variables into a React App

eidellev

Lev Eidelman Nagar

Posted on February 19, 2020

Injecting Environment Variables into a React App

When creating a react app using create-react-app, we may sometimes want to inject some environment variables at build time.
For instance, our team wanted to console.log the build time, app version and some git information when the app starts.

This is the solution we came up with.

The Build script

We added a node script to scripts/build.js. The script uses shelljs to append information to the environment and run react-scripts and simple-git to execute git commands.

const path = require('path');
const shell = require('shelljs');
const simpleGit = require('simple-git');
const { version } = require('../package.json');

const args = process.argv.slice(2);
const isDev = args.includes('--dev');

if (!shell.which('git')) {
  shell.echo('Cannot build without git');
  shell.exit(1);
}

if (!shell.which('yarn')) {
  shell.echo('Cannot build without yarn');
  shell.exit(1);
}

const workingDir = path.resolve(__dirname, '../');
const git = simpleGit(workingDir);

function getCurrentBranch() {
  return new Promise((fulfill, reject) => {
    git.status((err, status) => {
      if (err) {
        reject(err);
        return;
      }

      fulfill(status.current);
    });
  });
}

function getCurrentCommit() {
  return new Promise((fulfill, reject) => {
    git.revparse(['HEAD'], (err, hash = '') => {
      if (err) {
        reject(err);
        return;
      }
      fulfill(hash.slice(0, 7));
    });
  });
}

(async () => {
  try {
    const branch = await getCurrentBranch();
    const commit = await getCurrentCommit();
    const buildTime = new Date().toUTCString();

    shell.env.REACT_APP_VERSION = version;
    shell.env.REACT_APP_GIT_BRANCH = branch;
    shell.env.REACT_APP_GIT_COMMIT = commit;
    shell.env.REACT_APP_BUILD_TIME = buildTime;

    if (isDev) {
      shell.exec('yarn react-scripts start');
      return;
    }

    shell.exec('yarn react-scripts build');
  } catch (err) {
    shell.echo('Failed to gather build info', err);
    shell.exit(1);
  }
})();

Enter fullscreen mode Exit fullscreen mode

We substitute react-script in package.json for our build script:

...
  "scripts": {
    "start": "node ./scripts/build --dev",
    "build": "node ./scripts/build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  }
...

Enter fullscreen mode Exit fullscreen mode

In the app

We added src/utils/printBuilInfo.js. It prints out our environment variables in a style inspired by Vue devtools.

function print(title, info) {
  // eslint-disable-next-line
  console.log(
    `%c ${title} %c ${info} %c`,
    'background: #f26d21; padding: 1px; border-radius: 3px 0 0 3px;  color: #fff',
    'background: #009eed; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff',
    'background:transparent',
  );
}

export default function printBuildInfo() {
  print('Version', process.env.REACT_APP_VERSION);
  print('Branch', process.env.REACT_APP_GIT_BRANCH);
  print('Commit', process.env.REACT_APP_GIT_COMMIT);
  print('Build Time', process.env.REACT_APP_BUILD_TIME);
}

Enter fullscreen mode Exit fullscreen mode

We use it in src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import App from './App';
import printBuildInfo from './utils/printBuildInfo';
import './styles/index.scss';

printBuildInfo();

ReactDOM.render(<App />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
Enter fullscreen mode Exit fullscreen mode

💖 💪 🙅 🚩
eidellev
Lev Eidelman Nagar

Posted on February 19, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related