Webpack 4 + React + CSS modules stripping all classes from CSS bundle
See original GitHub issueWhen using CSS modules with React and Webpack 4, all classes are removed from the CSS bundle.
In the options for css-loader
, if I have modules: true
the CSS bundle is totally empty.
If I comment that out, the CSS bundle is as expected with all unused classes removed, however the JS bundle no longer has the CSS classes on the component elements.
If I add the SCSS files to the entry
and do not use CSS modules, the CSS bundle is correct as well.
The issue appears to be when combining modules: true
and purgecss.
The same is true is I do not use mini-css-extract-plugin
and let the CSS go into the bundle.
Here is my Webpack config:
const path = require("path");
const glob = require("glob");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const PurgecssPlugin = require("purgecss-webpack-plugin");
const PATHS = {
src: path.join(__dirname, "src")
};
module.exports = {
entry: "./src/App.js",
output: {
filename: "bundle.js",
path: path.join(__dirname, "dist")
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: "styles",
test: /\.css$/,
chunks: "all",
enforce: true
}
}
}
},
module: {
rules: [
{
test: /\.js/,
loader: "babel-loader",
include: __dirname + "/src",
query: {
presets: ["react"]
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
camelCase: true,
importLoaders: 1,
localIdentName: "[name]--[local]--[hash:base64:5]"
}
},
"sass-loader"
]
}
]
},
plugins: [
new CopyWebpackPlugin([{ from: `src/index.html`, to: "index.html" }]),
new PurgecssPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true })
}),
new MiniCssExtractPlugin({
filename: "[name].css"
})
]
};
Here is the entry:
import React from "react";
import ReactDOM from "react-dom";
import Sub from "./Sub";
import { appContainer } from "./App.scss";
function App() {
return (
<div className={appContainer}>
Hi from app.
<Sub />
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
Issue Analytics
- State:
- Created 5 years ago
- Comments:13 (1 by maintainers)
Top Results From Across the Web
[PURGECSS]: Webpack 5 + VueJS + CSS modules stripping ...
When using CSS modules with VueJS and Webpack 5, all classes are removed from the CSS bundle. In the options for css-loader, ...
Read more >style-loader - webpack
Automatically injects styles into the DOM using multiple <style></style> . It is default behaviour. ... import styles from "./styles.css"; const divElement = ...
Read more >32 - Enable and Use CSS Modules In React - Geekstrick
That is possible, and it is possible in the setup we use here. We can use a feature named CSS modules and I...
Read more >Eliminating Unused CSS - SurviveJS
It walks through your code and figures out which CSS classes are being used as often there is enough information for it to...
Read more >Eliminating Unused CSS | webpack surviveJS - GitHub Pages
It walks through your code and figures out which CSS classes are being used. Often there is enough information for it to strip...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
webpack: 4.29.6 react: 16.8.6 CSS modules: enabled @fullhuman/postcss-purgecss: 1.2.0
I had this problem too but I managed to solve it. Its like PurgeCSS *Plugin* is invoked in a intermediate phase when React components still have the original CSS classes names set in JSX while CSS modules classes have the new hashed name. Since PurgeCSS parses every JS/JSX/HTML file extracting from them all used CSS classes names, when it compares these last with the new hashed CSS classes names obviously none of them is used because each name is different from the other and thus all your CSS get purged. To make things work, we will use postcss-loader and @fullhuman/postcss-purgecss. You will need the following packages:
You can also install them as dev dependencies.
Obviously you need to eject by running
yarn run eject
ornpm run eject
.You also need to remove PurgecssPlugin from Webpack plugins list.
This code snippet is the piece of my Webpack configuration which is responsible of hashing and purging of CSS. It should work straightforward, I hope I didn’t leave any pieces back.
P.S. Since I use both Tailwind CSS and SASS to style my HTML, in PurgeCSS configuration I had to write an extractor to prevent Tailwind classes to get purged. You can delete it if you don’t need it.
Furthermore you can use regular module syntax in your JSX just like this:
One last thing, I had to change the CSS “syntax” to something like this