Using Webpack variables to conditionally load assets in React

Wouldn't it be great if we could re-use a web application just with different colours and header and footer links, without a huge copy and paste of the entire repo. This is where webpack variables can come in.


package.json commands


Inside the scripts section of our package.json, we pass a variable to the command which we can re-use to conditionally load assets.

{
  'name': 'app-name',
  'version': '1.0.0',
  'description': 'Application name',
  'main': 'index.js',
  'scripts': {
    'build': 'webpack --config webpack.prod.js',
    'start:red': 'cross-env THEME=red webpack-dev-server --hot --open --host 0.0.0.0 --port 3000 --config webpack.dev.js',
    'start:blue': 'cross-env THEME=blue webpack-dev-server --hot --open --host 0.0.0.0 --port 3001 --config webpack.dev.js',
    'test': 'jest'
  },


The important bits here are the start scripts i.e. 'start:red' and 'start:blue'.


We would run them like this 'npm run start:red'


But first, we have to wire up our webpack to pass through the 'THEME' flag.


We do this inside our webpack file. I like to separate my dev and prod webpack files and use a webpack common file to use across both environments.


So inside my webpack.dev.js file I need to firstly require webpack and also pass through 'THEME' from the process environment:

const webpack = require('webpack');

const THEME = JSON.stringify(process.env.THEME);


Then we also need to add the global constant using webpack's awesome define plugin. Inside your module.exports add this to your plugins like this:

plugins: [
  new webpack.DefinePlugin({
    THEME
  })
]


Then, where we would normally import our css for the react app (probably in the index.js file), we can do this:

if( THEME === 'red' ) require('../scss/red_styles.scss'); else require('../scss/blue_styles.scss');


Instead of this:

import '../scss/app.scss';


You can also take it a step further and use the value returned by 'THEME' in the react render method to conditionally render different content like this:

render() {
  return {
    <div>
      {( THEME === 'red' ) ? 'Hello RED!' : ''}
    </div>
  }
}