useFeatureFlag: Feature Flags with React and Webpack

useFeatureFlag: Feature Flags with React and Webpack

Photo by Ferenc Almasi on Unsplash

Feature flags are an instrumental part of continuous deployment. It’s essential to be able to gradually roll out features, but keep them hidden from the production environment until you’re ready to flip the switch. It’s fairly easy to implement this in ES6 with React and Webpack. Here’s an example of how I’ve done it in the past.

Webpack Configuration

To configure the feature flags, I like to use environment variables. If I’m adding a feature flag for a Recommendations feature, I would call it FEATURE_RECOMMENDATIONS in the environment, and my entry in the .env file would appear as FEATURE_RECOMMENDATIONS=false when disabling the feature or FEATURE_RECOMMENDATIONS=true when enabling, usually in the local environment. The reason I prefix it with features is it’s easier to see all the feature environment variables at once when they all share the same prefix.

FEATURE_RECOMMENDATIONS=true
FEATURE_INSTANT_CART=false
FEATURE_THUMBS_UP_BUTTON=false

To add this functionality to webpack, you’ll want to take advantage of the DefinePlugin package.


const { filter, test, keys, fromPairs, map, match } = require('ramda');

const env = dotenv.config({ path: ".env.local" }).parsed;

const featureKeys = filter(test(/^FEATURE/), keys(env));
const FeatureFlags = fromPairs(map(key => [match(/FEATURE_([\w\W]+)/, key)[1], env[key]], featureKeys));

module.exports = {plugins: [new webpack.DefinePlugin({ ...env, FeatureFlags })]};

This will add the FeatureFlags global variable to our project, which our useFeatureFlag function will take advantage of.

useFeatureFlag

The React portion of this solution will accept the name of the feature, and optionally a component to decorate, and return a boolean flag we can use, and optionally a decorated component with the boolean flag added as a prop. The code for this is as follows.

https://gist.github.com/prokizzle/66725bdf96cb8d19b65fcafea1ac7f4d

Using it is fairly straight forward. We have a few different options, and I’ll show you all of them.


import React from 'react';
import useFeatureFlag from './useFeatureFlag';
import RecommendationsComponent from './Recommendations.js';

const { 
  DecoratedComponent: Recommendations, 
  featureEnabled: recommendationsFeatureEnabled,
  FeatureFlag
} = useFeatureFlag({
  Component: RecommendationsComponent,
  feature: 'RECOMMENDATIONS'
});

const ExampleComponent = () => {
  const pageTitle = recommendationsFeatureEnabled ? 'Recommendations' : 'Saved Items';
  
  return <div>
    <h1>{pageTitle}</h1>
      <Recommendations />
      <FeatureFlag>
        <Dependency recommendations={recommendations} />
      </FeatureFlag>
    </div>;
};

import React from 'react';

const Recommendations = ({ featureEnabled }) => {
  if (!featureEnabled) {
    return <div>Page Not Found</div>
  }
  
  return <div>
    <h1>Recommendations</h1>
    <div>{recommendations}</div>
  </div>;
  
 }
 
 export default Recommendations;

That’s about it. Now you can wrap features with flags, and toggle them on and off via your environment variables.