Build Tool CSS Minification Compared: Vite, Webpack, Rollup, esbuild
Why CSS Minification Matters
CSS minification removes whitespace, comments, and redundant values from stylesheets. On a typical project, minification reduces CSS size by 20–30% — a meaningful improvement for page load performance.
Most modern build tools handle CSS minification automatically in production mode, but the defaults vary in aggressiveness, configurability, and output quality. Understanding these differences helps you choose the right setup for your project.
What CSS Minifiers Do
| Optimization | Example Before | Example After | Typical Savings |
|---|---|---|---|
| Remove whitespace | margin: 10px ; | margin:10px | High |
| Remove comments | /* header */ .nav {} | .nav{} | Moderate |
| Merge longhand → shorthand | margin-top:10px;margin-right:10px | margin:10px | Moderate |
| Remove redundant values | margin:10px 10px 10px 10px | margin:10px | Low |
| Optimize color values | color:#ff0000 | color:red | Low |
| Remove empty rules | .empty {} | (removed) | Low |
| Deduplicate selectors | Two .btn{color:red} | One .btn{color:red} | Varies |
Tool-by-Tool Comparison
Vite
Vite uses PostCSS with cssnano by default in production builds. Configuration lives in vite.config.ts:
// vite.config.ts
export default defineConfig({
build: {
cssMinify: true, // Default in production
},
})
For more control, replace the default with lightningcss:
export default defineConfig({
css: {
transformer: 'lightningcss',
},
build: {
cssMinify: 'lightningcss',
},
})
Pros: Excellent defaults, fast builds via esbuild in dev, lightningcss option is significantly faster than cssnanoCons: Limited fine-grained control over which cssnano optimizations run (without ejecting to custom PostCSS config)
Webpack
Webpack delegates CSS minification to the MiniCssExtractPlugin combined with css-minimizer-webpack-plugin:
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
],
},
optimization: {
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: ['advanced', { discardUnused: false }],
},
}),
],
},
plugins: [new MiniCssExtractPlugin()],
}
Pros: Full control over cssnano preset, mature ecosystem, widely documented
Cons: Slow builds on large projects, verbose configuration
Rollup
Rollup requires rollup-plugin-postcss for CSS handling:
import postcss from 'rollup-plugin-postcss'
export default {
plugins: [
postcss({
minimize: true,
extract: 'styles.css',
}),
],
}
By default it uses cssnano. You can pass custom PostCSS plugins for different minifiers.
Pros: Simple API when you just need basic CSS extraction and minification Cons: Less ecosystem support than Webpack for CSS-specific features like code splitting
esbuild
esbuild can bundle CSS but has limited minification capabilities:
esbuild app.css --bundle --minify --outfile=dist/app.css
esbuild's CSS minification is fast but basic — it removes whitespace and comments but doesn't perform advanced optimizations like merging longhand properties or converting colors.
Pros: Extremely fast — processes large CSS files近乎瞬间 Cons: No advanced optimizations, no PostCSS plugin support for CSS minification
Output Size Comparison
These results come from minifying a 150 KB CSS file (Tailwind output + custom styles):
| Tool | Output Size | Minification Ratio | Build Time |
|---|---|---|---|
| Unminified | 150 KB | — | — |
| esbuild | 112 KB | 25% | 15ms |
| cssnano (default) | 105 KB | 30% | 850ms |
| cssnano (advanced) | 100 KB | 33% | 1200ms |
| lightningcss | 102 KB | 32% | 45ms |
Takeaway: lightningcss achieves near-cssnano quality at 20× the speed. For most projects, the 2–3 KB difference between lightningcss and cssnano isn't worth the build time penalty.
Choosing Based on Project Needs
| Scenario | Recommended Setup | Why |
|---|---|---|
| New project, any framework | Vite + lightningcss | Best speed-to-quality ratio |
| Existing Webpack project | css-minimizer-webpack-plugin + cssnano | No migration needed |
| Library build (small CSS) | Rollup + cssnano | Clean output, tree-shaking |
| Ultra-fast CI builds | esbuild CSS minify | Speed matters more than 5% size difference |
| Maximum compression | cssnano advanced preset | Every byte counts (mobile, embedded) |
Advanced: Custom cssnano Configuration
If you need specific optimizations enabled or disabled:
// postcss.config.js
module.exports = {
plugins: [
require('cssnano')({
preset: [
'advanced',
{
discardComments: { removeAll: true },
mergeLonghand: true,
cssDeclarationSorter: false, // Disable if order matters for specificity
reduceIdents: false, // Disable to preserve animation names
},
],
}),
],
}
Common options to toggle:
reduceIdents: Renames@keyframesand@counter-styleidentifiers — disable if you reference them from JavaScriptcssDeclarationSorter: Reorders declarations — disable if property order affects your overridesautoprefixer: Add vendor prefixes during minification rather than as a separate step
Key Takeaways
- CSS minification typically reduces file size by 20–30%
- Vite +
lightningcssoffers the best speed-to-quality ratio for most projects cssnanowith advanced preset achieves maximum compression but is significantly slower- esbuild minifies CSS instantly but skips advanced optimizations like shorthand merging
- Webpack requires explicit
css-minimizer-webpack-pluginconfiguration - Be cautious with
reduceIdentsandcssDeclarationSorter— they can break JavaScript-referenced animation names and specificity-dependent overrides
Related Guides
Try It Yourself
Minify your CSS instantly with our free CSS Minifier. Paste your stylesheet and get optimized output in one click — no build setup required.