Render CSS on Server Side with React and Isomorphic-Style-Loader

Daniel Mai
Sep 8, 2018 · 3 min read

If you come here because you have the error:

TypeError: Cannot read property 'apply' of undefined at WithStyles.componentWillMount

then you’re in the right place! Read on to see the solution.

Doing server-side code for a React app is not as simple as you may think. Aside from running a customized server and configuring routes, you have to deal with the fact that modules you use in your React app are not meant to run on a server environment. So you’ll end up having errors like window is not defined or document is not defined. Global variables like window and document are available on the web browser only. On the server side, you’re out of luck.

You can wrap your logic and limit such modules to run only on the client browser (conditional require statements based on the environment, which will get ugly pretty quickly). Or you can opt for modules that support Server Side Rendering (SSR) out of the box.

I’m facing the same problem when trying to load CSS styles to my React components on the Node environment. It did not work because NodeJS does not understand what the heck CSS is! So instead of telling Webpack to use style-loader or css-loader for CSS files, I decide to try isomorphic-style-loader. It works for me, so I’m going to share with you how to implement this loader in your current React project.

There are other options that achieve the same goal, such as styled-components or styled-jsx. Play around with them to see which one suits your app better.

The documentation is okay, but it does not cover everything. Let’s start step by step.

1. Install the loader

$ npm install isomorphic-style-loader --save-dev

2. Make sure to use it on both server and browser Webpack configs.

// webpack.browser.js and webpack.server.js
{
test: /\.css$/,use: ['isomorphic-style-loader', { loader: 'css-loader' }]}

3. Use it in React components.

If you use CSS modules, it is pretty straightforward. Just wrap your component with the withStyles method.

4. Wrap your App in a Context in both server and client side

Now here’s the (undocumented) tricky part. In order to achieve SSR, you’ll need two versions of App.js, one running on the server and one on the browser. You need to load CSS styles with isomorphic-style-loader on both of them. I believe many people reading the official documentation will have the above error, because they don’t provide enough Context in their App.js so that withStyles can execute properly.

withStyles has the method insertCSS(_context, styles). If the _context is undefined, it will throw the error.

So you need to provide a proper context for your App.js.

5. Create a ContextProvider in the same directory of App.js

ContextProvider.js

5. Wrap your App component in your root client file.

Don’t forget to create a context and add an insertCss function to it.

index.js (client side)

6. Wrap your App component in your server file.

Do the same thing.

index.js (server side)

7. Run the server and make sure that CSS styles are loaded on both server and client side

If everything is working, your app will load insanely fast, since initial render is done on the server, after that React will take place. And SEO performance is not an issue anymore. I think configuring your React app to be isomorphic/ universal is worth the hassle because of many benefits it provides.

If you have any question, post a comment below. I’ll be happy to answer :)

Happy Coding!

Daniel Mai

Written by

I develop experiences that make peoples’ lives better.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade