MiniCssExtractPlugin is garbling and obfuscating my class names
Asked Answered
T

2

6

I am using MiniCssExtractPlugin in my typescript and webpack project.

My webpack config for the MiniCssExtractPlugin looks like

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

module.exports = {
   entry: './src/index.tsx',
   mode: "development",
   output: {
      path: path.resolve(__dirname, "build"),
      filename: 'bundle.js'
   },
   module: {
      rules: [
         {
            test: /\.tsx?$/,
            loader: "awesome-typescript-loader"
         },
         {
            enforce: "pre",
            test: /\.js$/,
            loader: "source-map-loader"
         },
         {
            test: /\.scss$/,
            use: [
               MiniCssExtractPlugin.loader,
               {
                 loader: "css-loader",
                 options: {
                   modules: true,
                   sourceMap: true,
                   importLoader: 2
                 }
               },
               "sass-loader"
            ]
         }
      ]
   },
   plugins: [
      new HtmlWebpackPlugin({
         template: "./index.html"
      }),
      new MiniCssExtractPlugin({
         filename: "foo.css",
         chunkFilename: "[id].css"
      })],
   devtool: "source-map",
   resolve: {
      extensions: [".js", ".ts", ".tsx"] 
   }
}

Now the scss file in my project has this fragment

h1 {
   border-bottom: 3px solid #880055;
   display: inline;
}

.container {
   font-size: 1.3rem;
}

.is-completed {
   text-decoration: line-through;
   color: #00ff00;
}

when my application is run using npm start I can see that the heading H1 has a underline of the color 880055. So this means that my scss file was read correctly.

If I go into chrome developer tools and go into network tab and look for CSS. I can see a foo.css being downloaded. If I look into the content of foo.css

It doesn't have my "is-completed" class. instead I see something like

h1 {
  border-bottom: 3px solid #880055;
  display: inline; }

.pxcHIyOVHeytUeG27u4TO {
  font-size: 1.3rem; }

._1Z5_KVJNKd1X2P3HKM63j {
  text-decoration: line-through;
  color: #00ff00; }

So element classes like h1 are good, but everything else is garbled. What's going on?

Turgot answered 2/4, 2018 at 21:37 Comment(0)
D
9

When you set modules: true in your CSS config you are telling the css-loader to use CSS-Modules to scope your class names to a particular file.

Delwin answered 3/4, 2018 at 7:11 Comment(0)
M
6

You can use the localIndentName query paramater in the css-loader options to specify what you want your generated class (identifier) to look like in development and/or in prod. See example below for what solved this for me.

 module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentName: '[name]-[local]--[hash:base64:5]',
          },
        },
      },
    ],
  },
};

If I were to use the configuration in the example above and the name of the component that I was rendering was called HelloWorld and a class used in that component was .container, if I were to run my app (dev or prod) and inspect the element in the devtools the class on my HelloWorld component appear as follows:

<div class="HelloWorld-container--16ABh"> Hello World </div>

You can play around with what you set as your localIdentName and how many characters of the hash you show.

See the documentation for the localIdentName query param here: https://github.com/webpack-contrib/css-loader#localidentname

Maintop answered 6/1, 2020 at 1:41 Comment(1)
i get css transformed to different hash name using your above webpack.config.js you provide. but i am using raw html no js that class name is as it is it did not change anything so how can i post process my html class according to new hash generated css classHarhay

© 2022 - 2024 — McMap. All rights reserved.