Минификация CSS и JS
Минификация — удаление из исходного кода пробелов, комментариев, переносов строк и замена длинных идентификаторов на короткие без изменения функциональности, что уменьшает размер файлов на 20-60% и ускоряет их загрузку и парсинг.
Зачем нужно
Каждый килобайт JS требует загрузки, парсинга и компиляции — это дорогие операции, особенно на мобильных устройствах. Минификация вместе со сжатием (gzip/brotli) снижает размер бандла в 3-5 раз по сравнению с исходным кодом.
Где используется
- Production сборка любого веб-приложения (Vite, webpack, esbuild, Rollup)
- CSS фреймворки (Tailwind — агрессивный purge + минификация)
- Inline CSS/JS в HTML
Основной контент
Что удаляет минификатор
// Исходный код (не минифицированный):
function calculateDiscount(price, discountPercent) {
// Применяем скидку к цене
const discountAmount = price * (discountPercent / 100);
return price - discountAmount;
}
// После минификации (esbuild/terser):
function c(a,b){const d=a*(b/100);return a-d}
// Или ещё агрессивнее:
const c=(a,b)=>a-a*(b/100);
Инструменты минификации
| Инструмент | Скорость | Размер | Использование |
|---|---|---|---|
| esbuild | Очень быстрый | Хороший | Vite, бандлеры |
| SWC | Быстрый | Хороший | Next.js, Parcel |
| Terser | Медленный | Отличный | Webpack (prod) |
| LightningCSS | Быстрый | Отличный | CSS |
| cssnano | Медленный | Отличный | PostCSS |
Vite production сборка
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
minify: 'esbuild', // 'esbuild' (быстро) | 'terser' (меньше)
cssMinify: 'lightningcss',
terserOptions: {
compress: {
drop_console: true, // Удалить console.log в prod
drop_debugger: true,
pure_funcs: ['console.log', 'console.info'],
},
},
rollupOptions: {
output: {
// Разделить по чанкам для лучшего кеширования
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
},
},
},
},
});
Tree Shaking — удаление неиспользуемого кода
// Наряду с минификацией, tree shaking удаляет мёртвый код
// library.js (ES modules обязательны для tree shaking)
export function usedFunction() { return 'used'; }
export function unusedFunction() { return 'never imported'; }
// app.js
import { usedFunction } from './library'; // Только usedFunction попадает в бандл
usedFunction;
// unusedFunction — удалена при сборке
// ВАЖНО: CommonJS (require) не поддерживает tree shaking!
// Всегда используйте ES modules (import/export) в библиотеках
CSS: PurgeCSS + cssnano
// postcss.config.js
const purgecss = require('@fullhuman/postcss-purgecss');
const cssnano = require('cssnano');
module.exports = {
plugins: [
// Tailwind или ваши классы
require('tailwindcss'),
// Удалить неиспользуемый CSS
purgecss({
content: ['./src/**/*.{html,jsx,tsx,vue}'],
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || ,
}),
// Минифицировать оставшийся CSS
cssnano({ preset: 'default' }),
],
};
Анализ размера бандла
# webpack-bundle-analyzer
npx webpack-bundle-analyzer dist/stats.json()
# Vite bundle visualizer
npm run build -- --report
# Rollup visualizer плагин:
import { visualizer } from 'rollup-plugin-visualizer';
plugins: [visualizer({ open: true, gzipSize: true })]
Частые ошибки
- Минификация в development — замедляет сборку и HMR без пользы
- Отключение source maps в production — невозможно диагностировать ошибки
- Только минификация без tree shaking — мёртвый код остаётся
- Агрессивный mangle у сторонних библиотек — может сломать reflection-зависимый код