Reputation: 462
I want to purge unused CSS from the Clarity UI CSS file, in a setup using webpack and purgecss-webpack-plugin.
However, while the size of the CSS file is reduced from 565kB to 172kB, it should be reduced to 0kB since I don't use any of it. If I do the same thing using Bootstrap, the filesize is reduced to 1kB.
Why is that behaviour and is there a fix?
My folder structure is as follows:
|-dist
|
|-node_modules
|
|-src
|--index.js
|
|.babelrc
|package.json
|webpack.config.js
My package.json:
{
"name": "webpack-clarity",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"start": "node ./index.js",
"build": "webpack"
},
"dependencies": {
"@clr/ui": "^4.0.0",
"bootstrap": "^4.5.2"
},
"devDependencies": {
"@babel/core": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"babel-loader": "^8.1.0",
"css-loader": "^3.6.0",
"glob": "^7.1.6",
"html-webpack-plugin": "^4.3.0",
"mini-css-extract-plugin": "^0.9.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"purgecss-webpack-plugin": "^2.3.0",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12"
}
}
webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const glob = require("glob");
const PurgeCSSPlugin = require("purgecss-webpack-plugin");
module.exports = {
mode: "production",
entry: "./src/index.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
optimization: {
minimizer: [new OptimizeCssAssetsPlugin(), new TerserPlugin()],
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: "[name].css" }),
new PurgeCSSPlugin({
paths: glob.sync("./src/**/*.js", { nodir: true }),
}),
],
};
.babelrc
{
"presets": [
[
"@babel/preset-env",
{"modules": false}
]
]
}
index.js
import "../node_modules/@clr/ui/clr-ui.min.css";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
Upvotes: 0
Views: 3511
Reputation: 8491
A little bit late with this answer, but maybe it will help.
TLDR: PurgeCSS only removes unused CSS classes by default. We need to enable PurgeCSS to also remove unused CSS variables, keyframes & font-face declarations.
Add the following options for PurgeCSSPlugin:
{
paths: glob.sync("./src/**/*.js", { nodir: true }),
// add the following options
fontFace: true,
variables: true,
keyframes: true,
}
Details:
Considering that in src/index.js
we only import Clarity UI CSS file:
import "../node_modules/@clr/ui/clr-ui.min.css";
let's take a look at the compiled CSS file (dist/[name].css])
. It has ~175 kb and it contains:
font-family: "Metropolis"
declarations with the font source inlined as a base64 stringTo make PurgeCSS to also remove unused CSS variables, keyframes & font-face declarations, we need to add the following options:
new PurgeCSSPlugin({
paths: glob.sync("./src/**/*.js", { nodir: true }),
// add the following options
fontFace: true,
variables: true,
keyframes: true,
}),
The compiled CSS file now has ~117kb.
Since the html
and body
tags have set a font declaration in ClarityUI CSS file, PurgeCSS will not remove @font-face declarations:
html {
font-family:Metropolis,"Avenir Next","Helvetica Neue",Arial,sans-serif;
font-family:var(--clr-font, Metropolis, "Avenir Next", "Helvetica Neue", Arial, sans-serif);
}
Tested with:
"@clr/ui": "^4.0.16"
"webpack": "^5.89.0",
"purgecss-webpack-plugin": "^5.0.0",
From the PurgeCSS docs:
- fontFace (default: false)
If there are any unused @font-face rules in your css, you can remove them by setting the fontFace option to true.
- keyframes (default: false)
If you are using a CSS animation library such as animate.css, you can remove unused keyframes by setting the keyframes option to true.
- variables (default: false)
If you are using Custom Properties (CSS variables), or a library using them such as Bootstrap, you can remove unused CSS variables by setting the variables option to true.
Upvotes: 1