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>
}
}