Implementing feature toggles for a React App using Webpack
Tags: featuretoggle, javascript, testing, webpack
Published: 2018-10-25 14:39:23

---
title: Implementing feature toggles for a React App using Webpack
published: true
description: Implementing feature toggle for a React App using Webpack
tags: feature toggle, javascript, testing, webpack
---

Feature switches/toggles are an important technique that can help us deploy code in various environments under different conditions without blocking other developers in the team (or other teams) from releasing their features. [Martin Fowler has an extensive article](https://martinfowler.com/articles/feature-toggles.html) on the topic, I won't focus on the theoretical part of it, I would like to show an implementation of feature flags in a react project.

Let's assume that we are working on a React Project where we have 4 environments, 

- Development (local development)
- Testing (where our tests are running aka NODE_ENV=test)
- Staging (Production like environment, minification bundling etc) 
- Production

and let's assume that we have a super experimental component that we would like to display on our Staging environment so we can QA it, but not on production.

```js
class ExperimentalButton extends Component {

  render() {
    return <Button.Primary {...this.props} />;
  }
}
```

Webpack has a plugin that can help us create feature flags, its called [DefinePlugin](https://webpack.js.org/plugins/define-plugin/)

```js
new webpack.DefinePlugin({
  'process.env': {
    SHOW_EXPERIMENTAL_BUTTON: true
  }
});
```

Usually in our projects we have `webpack.config.dev.js` and `webpack.config.production.js`, but not a config for staging, since we want the code on staging and production to be identical usually we deploy the production build there. Also we don't pass our source code through Webpack before running tests. So how would we differentiate between staging/production/development but avoid creating a `webpack.config.staging.js`?

In my case I created a `featureToggles.json` which looks like this:

```js
{
  "test": {
    "showExperimentalButton": true,
  },
  "development": {
    "showExperimentalButton": true,
  },
  "staging": {
    "showExperimentalButton": true,
  },
  "production": {
    "showExperimentalButton": false,
  }
}
```

To differentiate among stating/production/development in my `package.json` I pass a flag to the script

```
    "build:production": "npm run build",
    "build:staging": "npm run build -- --staging",
    "build:development": "npm run build -- --development",
```

In my `webpack.config.js` (shared configuration options for every environment) I do:

```js
const featureSwitches = require('./featureSwitches.json');

let features_env = process.argv[2] === '--staging' ? 'staging' : 'production';
features_env = process.argv[2] === '--development' ? 'development' : features_env;

...
...

new webpack.DefinePlugin({
  'process.env': {
    ...featureSwitches[features_env]
  }
});    
```

To display/hide our component we will do something like

```
{ process.env.showExperimentalButton ? <ExperimentalButton /> : null }
```

(Or we can go a step further and create a wrapper component `<FeatureToggle feature='showExperimentalButton'>`.)

There is a problem though, the previous is not working on the testing environment, since the code is not being passed through Webpack. So we are unable to write unit tests for the component. First we need to tell Jest to setup a few things before running the tests, we can do that with the `setupTestFrameworkScriptFile` option
and create a `jest.init.js`.

```
setupTestFrameworkScriptFile: '<rootDir>/jest.init.js',
```

In our `jest.init.js` file we will do:

```js
const featureSwitches = require('./config/featureSwitches');


Object.keys(featureSwitches.test).forEach((key) => {
  process.env[key] = featureSwitches.test[key];
});
```

Now we are able to run unit tests for our experimental component.