2

I am trying to setup a react app with latest versions. React 17, Webpack 5 and other modules.

I need css modules with styleName concept by using babel-plugin-react-css-modules

Trying to run the code shows the output but no styles are applied.

package.json

{
  "name": "react-app",
  "version": "1.0.0",
  "description": "React Template App",
  "author": "",
  "license": "ISC",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve --mode development",
    "build": "webpack --mode production",
    "format": "prettier --write \"src/**/*.js\"",
    "eslint-fix": "eslint --fix \"src/**/*.js\""
  },
  "dependencies": {
    "babel-plugin-react-css-modules": "^5.2.6",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/preset-env": "^7.12.11",
    "@babel/preset-react": "^7.12.10",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.2.2",
    "css-loader": "^5.0.1",
    "eslint": "^7.16.0",
    "eslint-config-react": "^1.1.7",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-react": "^7.21.5",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^4.5.0",
    "less": "^4.0.0",
    "less-loader": "^7.2.0",
    "mini-css-extract-plugin": "^1.3.3",
    "prettier": "2.2.1",
    "style-loader": "^2.0.0",
    "webpack": "^5.11.0",
    "webpack-cli": "^4.2.0",
    "webpack-dev-server": "^3.11.0"
  }
}

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    open: true,
    host: "localhost",
    compress: true,
    port: process.env.CLIENT_PORT,
    hot: true,
    quiet: false
  },
  module: {
    rules: [{
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader', 'eslint-loader']
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          MiniCssExtractPlugin.loader,
          // "less-loader",
          {
            loader: 'css-loader',
            options: {
              modules: true,
            }
          }
        ],
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: ["file-loader"]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "./index.html",
      favicon: "./public/favicon.ico"
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ],
  devtool: 'inline-source-map',
};

.babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
    [
      "babel-plugin-react-css-modules",
      {
        "webpackHotModuleReloading": true,
        "autoResolveMultipleImports": true
      }
    ]
  ]
}

home.js

import React from "react";

import "./style.css";

const Home = () => {
  return (
    <div styleName="container">
      <div styleName="title">Hello from Home CSS</div>
    </div>
  );
};

export default Home;

style.css

.container {
  display: flex;
  flex-direction: column;
}

.title {
  font-size: 24px;
  color: red;
}

1 Answer 1

2

That's interesting issue which requires us to do a few more things to make it work as following:

  • babel-plugin-react-css-modules isn't working properly with css-loader in case of generating the name. But luckily we have a work around by using a temporary fix of someone @dr.pogodin/babel-plugin-react-css-modules. So just install needed packages:
npm i -D @dr.pogodin/babel-plugin-react-css-modules postcss // postcss is required aslo
  • Reconfigure babel configuration by changing the name in .babelrc:
{
  // ...
  "plugins": [
    [
      "@dr.pogodin/babel-plugin-react-css-modules",
      {
        "webpackHotModuleReloading": true,
        "autoResolveMultipleImports": true
      }
    ]
  ]
}

  • Finally, we would change the class name to make it consistent between babel-plugin-react-css-modules and css-loader in webpack.config.js:
{
  test: /\.css$/,
  use: [
    // ...
    {
      loader: 'css-loader',
      options: {
        modules: {
          localIdentName: '[path]___[name]__[local]___[hash:base64:5]', // This pattern matches with the default in `babel-plugin-react-css-modules`
        },
      }
    }
  ],
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, after so much research finally something that works! Except unfortunately I can't use global stylesheets anymore.... So everything using className doesn't work anymore. Is a mix not possible?
It's possible to combine className and styleName using :global to define global classes in the scss file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.