Перейти к содержимому

11. Оптимизация бандла

Оптимизация Webpack — это искусство достижения баланса между размером бандла, скоростью загрузки и скоростью сборки. В production режиме Webpack автоматически включает ряд оптимизаций, но для максимального результата нужна ручная настройка.

// Автоматически включается в production:
optimization: {
minimize: true, // Минификация JS
minimizer: [new TerserPlugin()], // Через TerserPlugin
moduleIds: 'deterministic', // Стабильные ID модулей
chunkIds: 'deterministic',
concatenateModules: true, // Scope hoisting
usedExports: true, // Для tree shaking
mangleWasmImports: false,
}
Окно терминала
npm install --save-dev terser-webpack-plugin
const TerserPlugin = require('terser-webpack-plugin');
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true, // Многопоточная минификация
terserOptions: {
compress: {
drop_console: true, // Удалить console.log в production
drop_debugger: true,
pure_funcs: ['console.info', 'console.debug'],
},
mangle: {
safari10: true, // Совместимость с Safari 10
},
format: {
comments: false, // Удалить комментарии
},
},
extractComments: false, // Не создавать .txt с лицензиями
}),
],
}
Окно терминала
npm install --save-dev css-minimizer-webpack-plugin
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin({
minimizerOptions: {
preset: ['default', {
discardComments: { removeAll: true },
normalizeWhitespace: true,
colormin: true,
}],
},
}),
],
}
optimization: {
splitChunks: {
chunks: 'all',
maxInitialRequests: 30,
maxAsyncRequests: 30,
minSize: 20000, // 20 KB — минимальный размер чанка
maxSize: 244000, // 244 KB — разбить на меньшие части
cacheGroups: {
// Все node_modules в один vendor чанк
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
name: 'vendors',
},
// React в отдельный чанк (кешируется долго)
react: {
test: /[\\/]node_modules[\\/](react|react-dom|react-router)[\\/]/,
name: 'react-vendor',
chunks: 'all',
priority: 20,
},
// Общий код (используется в 2+ чанках)
common: {
name: 'common',
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
runtimeChunk: 'single', // Webpack runtime в отдельный файл
}
performance: {
hints: 'warning', // 'error' | 'warning' | false
maxEntrypointSize: 244000, // 244 KB — предупреждение для entry
maxAssetSize: 244000, // 244 KB — предупреждение для ассетов
assetFilter: (assetFilename) => {
return /\\.(js|css)$/.test(assetFilename);
},
}

Резко ускоряет повторные сборки:

cache: {
type: 'filesystem', // Кешировать на диск
cacheDirectory: path.resolve(__dirname, '.webpack-cache'),
buildDependencies: {
config: [__filename], // Инвалидировать кеш при изменении конфига
},
}
// Повторная сборка: 10s → 1s!
resolve: {
// Не проверять расширения лишний раз
extensions: ['.tsx', '.ts', '.js'], // Только нужные
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
// Не разрешать симлинки (ускоряет разрешение)
symlinks: false,
}
Окно терминала
# Генерация статистики
npx webpack --json > dist/stats.json
npx webpack-bundle-analyzer dist/stats.json
# Или через плагин:
new BundleAnalyzerPlugin({ analyzerMode: 'static' })

Ниже — интерактивная scoreboard оптимизации. Включайте оптимизации и смотрите как меняется размер бандла.