Customize Your ReactJS App Using styled-components, cross-env and webpack
Darya Talanina5 min read
As a web developer you may have already worked on a project where you had a single web application that was used by several different clients. The app would use a single code base but then it would need to have several variants, each personalized for a specific client:
- you may need to change the look and feel of the app (turquoise color theme background instead of a red one, text aligned on the right instead of left, different fonts and illustrations)
- the API calls you are making may vary depending on the client: each client could want to to have his own wording and you would need to fetch different i18n key-values depending on the client.
Imagine you develop a ticket selling platform and you offer a ticket selling app that is integrated in websites of your clients that include theaters, sports organisations and art galleries. You will most likely need to change the design and layout of the app for each of the clients so that it corresponds to the look and feel of their website.
In this article, I will show you how to have several personalized versions of your app while keeping a single code base.
- We will begin with a simple ReactJS poll app styled using a styled-components theme.
- Then we will create a second version of the app by adding another style theme and some structural differences.
- Lastly we will configure the build so that we are able to switch between the two versions of the app.
To help you easily set up the project there is a companion repository.
Initializing the project and creating a basic app
Start by checking out the project and installing the required packages:
git clone https://github.com/invfo/theming-with-webpack.git
cd theming-with-webpack
git checkout 514f5fd //checkout the commit pointing to the first version of the app
npm install
Then start the development server: npm start
and go to http://localhost:8080
in the browser. You should see the following poll with two options and a submit button.
Customizing the app
We will now create a second version of this polling app.
Changing the look and feel
Begin by adding a second theme and a switch between two themes based on a THEME
variable (which we will define later):
// index.js
const advancedTheme = {
background: 'linear-gradient(#68C5DB, #E0CA3C)',
button: {
border: '3px black dotted',
borderRadius: '23px',
fontSize: '30px',
marginTop: '17px',
padding: '5px 10px',
},
};
const theme = THEME === 'advanced' ? advancedTheme : basicTheme;
Pass the new theme to the ThemeProvider
:
<ThemeProvider theme={theme}> // index.js
Add a Title
component and display it based on the THEME
variable :
// index.js
const Title = ({children}) => <h1>{children}</h1>
class App extends React.Component {
render() {
return (
<ThemeProvider theme={theme}>
<Wrapper>
{ THEME === 'advanced' && <Title>Make your choice!</Title>}
...
Checkout the corresponding commit in the companion repository to see other minor changes that should be made.
Setting up the THEME variable
To be able to switch between the two app versions we need to define the THEME
variable which we will wire to an environment variable of the same name.
Begin by setting the THEME
environment variable at build time and making it available in our app.
Add a build command for each app version. These commands will set the THEME
environment variable to either red or blue :
// package.json
"scripts": {
"start:basic": "cross-env THEME=basic webpack-dev-server",
"start:advanced": "cross-env THEME=advanced webpack-dev-server"
}
You may wonder “‘Cross-env’? Why not simply use THEME=red webpack-dev-server
?”. This option would work fine on most OSs, but can be troublesome if you are using Windows.
Cross-env allows you to define environmental variables without worrying about particularities of the platform you are using. Install it: npm install --save-dev cross-env
Finally let’s put together everything we did in previous steps: make the THEME
environment variable available in the app code
// webpack.config.js
plugins: [
new webpack.DefinePlugin({
THEME: JSON.stringify(process.env.THEME),
}),
]
DefinePlugin
enables you to create global constants that are configured during compilation. Here we’re using it to define a THEME
variable that is usable in our app’s code. Its value will be equal to the THEME
environment variable set using cross-env.
For more info see the official webpack doc.
Now try out one of the new builds: npm run start:advanced
You should see the new version of the app:
To view the old version, run npm run start:simple
You can always get the latest app code version from the companion repository.
To sum up
So far we have learned how to:
- Define your app’s style and manage several CSS themes using styled-components and its ThemeProvider (check out the official docs for more information)
- Set up environment variables for the build using cross-env
- Make previously set environment variables available in your app’s code using webpack’s DefinePlugin
- Modify app’s content based on an environment variable value (on the example of )
Using the above concepts you can personalize your ReactJS app and have several builds, each of them generating an app with a specific look.
The proposed method is suitable when the personalization you need to make:
- concerns style or
- basic html structure (like changing input types or adding / hiding certain elements).
As with any other concept, you should not blindly apply it on your project but rather ask yourself if this is the most suitable solution. The proposed way of personnalizing can be used when different app variants are quite similar. But if your app versions are totally different, having many if
in your code will make it hard to maintain. In this case opt for another solution, for example having a separate “main” file for each version.
Have you already worked on a ReactJS app with several themes? How did you implement it?
Share your experience in the comments below or simply let me know if you have any questions or remarks!