How To Correctly Build a Multi-Environment React App
Tags: javascript, programming, react, softwaredevelopment
Published: 2024-01-19 21:10:34

When developing a React application, you might need to [deal with different environments](https://writech.run/blog/environment-based-error-handling-with-spring-boot-and-kotlin-b36b901135ad). Based on my experience, you should consider at least the following three [environments](https://en.wikipedia.org/wiki/Deployment_environment):

- Development

- Staging

- Production

Before deploying your React app to one of the last two environments, you need to build it. This is usually achieved by running a command aimed at creating a deployable build saved in your project's `build` folder.

Such a method has a tremendous downside. For example, you cannot launch many build commands in parallel. In fact, they all depend on the same folder. As a consequence, when dealing with several environments, this may be a bottleneck.

Plus, since every environment shares the same build folder, it is not intuitive to figure out what the target environment of your last build was. This can lead to errors as well.

Let's see how to avoid this by correctly building a multi-environment app in React.

## 1\. Installing the Required Dependencies

First of all, you need to add [`react-app-rewired`](https://www.npmjs.com/package/react-app-rewired) and [`env-cmd`](https://www.npmjs.com/package/env-cmd) to your project's dependencies. You can install both with the following command:

```shell
npm install react-app-rewired env-cmd --save
```

To be able to specify a custom build path, you have to change your [webpack configuration](https://webpack.js.org/configuration/). If you created your app by using [`create-react-app`](https://reactjs.org/docs/create-a-new-react-app.html), you might be forced to [eject your project](https://create-react-app.dev/docs/available-scripts/#npm-run-eject) — and this should be avoided if not strictly required.

This is where `react-app-rewired` comes into play!

**Note**: If your project already uses `react-app-rewired`, you can skip the following two steps.

Thanks to it, you can easily tweak the `create-react-app` webpack config. In order to make everything work, you need to follow the next two steps:

1. Create a valid `config-overrides.js` file in your root directory.

3. Change the existing references from `react-scripts` to `react-app-rewired` in the `scripts` section of your `package.json` file.

Before:

```json
{ 
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
}
```

After:

```json
{ 
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  }
}
```

You have just rewired your React app and are now ready to define environment-based build paths.

Plus, `react-app-rewired` allows you to achieve other fantastic goals. For example, [defining absolute path aliases to make your imports refactor-friendly](https://writech.run/blog/avoid-the-fear-of-refactoring-with-absolute-imports-in-react-804bce61dc31).

## 2\. Defining the Environment Files

Now, it is time to define a `.env` file for each of your environments. Such a file should contain whatever variable whose value depends on the current environment.

Let's define two `.env` files where we'll put the build path depending on the current environment.

The staging `.env.staging` env file:

```shell
REACT_APP_BUILD_PATH=build-staging
# ... (other environment variables)
```

The production `.env.production` env file:

```shell
REACT_APP_BUILD_PATH=build
# ... (other environment variables)
```

**Note**: As stated in the [Create React App documentation](https://create-react-app.dev/docs/adding-custom-environment-variables/), every environment variable must start with `REACT_APP_`.

## 3\. Using the Environment Variable

To read the build path from the environment file and use it as a base path for your builds, define a `config-overrides.js` file as follows:

```javascript
const path = require('path');

module.exports = {
    webpack: function(config, env) {
        // your webpack configs
        return config;
    },
    // the paths config used when your React app is builded
    paths: function(paths, env) {
        // reading the build path from the selected .env file
        const buildPath = process.env.REACT_APP_BUILD_PATH
        // defining "build" as a fallback path
        paths.appBuild = path.resolve(__dirname, buildPath ? buildPath : "build"); 
      
        return paths;
    }
}
```

As you can see, I ensured that the `appBuild` variable has a valid fallback value. This is extremely important. An empty, `null`, or `undefined` string could cause the build process to go terribly wrong, potentially affecting your entire code base.

Then, you should define a build command for each of your `.env` files. By employing `env-cmd`, you can pass a custom `.env` file to your build command by using the [`-f`](https://www.npmjs.com/package/env-cmd#using-custom-env-file-path) [flag](https://www.npmjs.com/package/env-cmd#using-custom-env-file-path).

Make sure the `scripts` section of your `package.json` file contains the following two lines:

```json
"build": "react-app-rewired build",
"build:staging": "env-cmd -f .env.staging npm run build"
```

By default, the `env.production` file will be used, so you do not need to specify it in the first command.

Now, you can create an environment-based build with the following commands.

For the staging environment:

```shell
npm run build:staging
```

For the production environment:

```shell
npm run build
```

The builds will be placed in the target path defined in the `REACT_APP_BUILD_PATH` environment variable. If you followed the example, your staging builds will be created in the `build-staging` folder, while your production builds in the `build` folder.

Et voilà! Each of your environments now has a dedicated build folder.

## Conclusion

Today, we looked at how to define a build folder for each environment of your React app. This way, you can launch different build commands in parallel and make sure that all of them have their own dedicated target folder. As I have just shown, this can easily be achieved by using `react-app-rewire` and `env-cmd`. Plus, such an approach can easily be extended to any number of environments.

Thanks for reading! I hope that you found this article helpful.
  
***
_The post "[How To Correctly Build a Multi-Environment React App](https://writech.run/blog/how-to-correctly-build-a-multi-environment-react-app-6ba4878e98ba/)" appeared first on [Writech](https://writech.run)._