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);
}
})();
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"
}
...
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);
}
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();
Top comments (1)
Hey Lev, thank you for your contribution. An improvement that you could do in your post is provide some comments in your script. It helps for beginners read easily your logic.
Thank you again this article helped me to solve an issue that I have.