37

The current practice for CSS with React components seems to be using webpack's style-loader to load it into the page in.

import React, { Component } from 'react';
import style from './style.css';

class MyComponent extends Component {
    render(){
        return (
            <div className={style.demo}>Hello world!</div>
        );
    }
}

By doing this the style-loader will inject a <style> element into the DOM. However, the <style> will not be in the virtual DOM and so if doing server side rendering, the <style> will be omitted. This cause the page to have FOUC.

Is there any other methods to load CSS modules that work on both server and client side?

willwill
  • 1,056
  • 3
  • 12
  • 21
  • You can try this postcss plugin: https://github.com/ctxhou/postcss-hash-classname . I found the style loader only limit to the webpack, so with this plugin, you can extract the css class name as a js object file. Then you can require this `style.js` and use the same code. Because this is a `.js` file, of course it can support server side rendering. You can check the repo to know more : ) – Chen-Tai Jan 05 '16 at 20:15
  • The problem I'm looking to solve is to make webpack inject the CSS into the virtual DOM so server side rendering also has CSS packed. I don't think that one has anything related to this task? – willwill Jan 06 '16 at 00:58
  • You mean you don't want to create another css file and only want the webpack to help you inject it ? – Chen-Tai Jan 06 '16 at 21:00

3 Answers3

12

You can use webpack/extract-text-webpack-plugin. This will create a independently redistributable stylesheet you can reference then from your documents.

Filip Dupanović
  • 32,650
  • 13
  • 84
  • 114
10

You can have a look at the isomorphic-style-loader. The loader was specifically created to solve this kind of issues.

However for using this you have to use an _insertCss() method provided by the loader. The documentation details how to use it.

Hope it helped.

Community
  • 1
  • 1
sandeep
  • 2,098
  • 1
  • 10
  • 13
4

For me, I am using the Webpack loader css-loader to implement CSS modules in isomorphic application.

On server side, the webpack config will be like this:

  module: {
    rules: [
      {
        test: /\.(css)$/,
        include: [
          path.resolve(__dirname, '../src'),
        ],
        use: [
          {
            // Interprets `@import` and `url()` like `import/require()` and will resolve them
            loader: 'css-loader/locals',
            options: {
              modules: true,
              localIdentName: '[name]__[local]--[hash:base64:5]'
            }
          },
        ],
      },
    ]
  }

On client side, the webpack config looks like this

          {
            // Interprets `@import` and `url()` like `import/require()` and will resolve them
            loader: 'css-loader',
            options: {
              modules: true,
              localIdentName: '[name]__[local]--[hash:base64:5]'
            }
          },

Off course, if you are using SASS, you need to use sass-loader to compile scss to css, and postcss-loader can help to add the autoprefixer.

Eric Tan
  • 1,377
  • 15
  • 14
  • when mention sass, sass-loader, autoprefixer etc - do I also need to setup webpack to handle those for the server-side? – user3125823 Sep 20 '19 at 21:13
  • yes, you need to setup those up for server side as well. – Eric Tan Sep 23 '19 at 04:44
  • Is there a way to do this using only one set of config - for example, creating a library which will be used for _either_ server- or client-side rendering? (Unknown at build time) – Tom Pietrosanti Jun 16 '21 at 16:15