Search code examples
webpackstyluswebpack-2css-modules

Add stylus to a webpack 2 app which has css modules


I have a webpack 2 app which uses css modules

I now just want to start using stylus as well.

I guess the solution is to update my webpack.config.js:

current webpack.config.js:

var path = require('path')
var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [

      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader'
        }
      },

      {
        test: /\.css$/,
        loader: 'style-loader'
      },

      {
        test: /\.css$/,
        loader: 'css-loader',
        query: {
          modules: true,
          localIdentName: '[name]__[local]___[hash:base64:5]'
        }
      },

    ]
  },
  resolve: {
    extensions: ['.js'],
    modules: [
      path.join(__dirname, 'src'),
      "node_modules"
    ]
  },

  plugins: [
    new ExtractTextPlugin( { filename: 'style.css', allChunks: true }),
  ],
}

so into the rules array in the config, I added:

  {
  test: /\.styl$/,
  use: [
    'style-loader',
    'css-loader',
    {
      loader: 'stylus-loader',
    },
  ],
},

EDIT: I then added:

var hook = require('css-modules-require-hook');
var stylus = require('stylus');

hook({
  extensions: ['.styl'],
  preprocessCss: function (css, filename) {
    return stylus(css)
      .set('filename', filename)
      .render();
  },
});

to the top of webpack.config.js as per css-modules-require-hook however I am unsure if the hook is supposed to go at the top of the webpack.config.js file and then if I need to somehow call the hook inside the webpack.config module.exports

I have added one .styl file:

logo/index.styl:

.img {
  width: 300px;
  height: 228px;
}

and I use it like this:

import styles from './index.styl'

function view() {
return (<img className={`${styles.img}`}
              src="src/img/logo_transparent_background.png"
            />)
}

The output html inspected in the developer console shows:

<img class="undefined" src="src/img/logo_transparent_background.png">

Any ideas why?


Solution

  • You don't have stylus_plugin installed, but you can't install it because there is no such package in the npm registry. And in fact that was supposed to be an example use of plugins you could use (e.g. poststylus). To be fair that wasn't quite clear from the stylus-loader Readme and has just been mentioned in the GitHub issue Error: Cannot find module 'stylus_plugin' #155.

    So just remove this non-existing plugin and it should work.

    Edit

    Now to your other question: Why do the stylus modules not work?

    Well you need to enable css-modules for your .styl files as well. And while on that subject you should also only have one .css rule and include both style-loader and css-loader in there, otherwise they will be applied separately, not in sequence. So your modules.rules should look like this:

    module: {
      rules: [
        {
          test: /\.js$/,
          use: {
            loader: 'babel-loader'
          }
        },
        {
          test: /\.css$/,
          use: [
            'style-loader',
            {
              loader: 'css-loader',
              options: {
                modules: true,
                localIdentName: '[name]__[local]___[hash:base64:5]'
              }
            }
          ]
        },
        {
          test: /\.styl$/,
          use: [
            'style-loader',
            {
              loader: 'css-loader',
              options: {
                modules: true,
                localIdentName: '[name]__[local]___[hash:base64:5]'
              }
            },
            'stylus-loader'
          ],
        },
      ]
    },