Webpack + React. Как уменьшить бандл в 15 раз
Ясной инструкции по сборке webpack для продакшена я не нашел. Поэтому решил написать эту статью. Надеюсь, пригодится. Существует множество сборщиков скриптов. Я выбрал для себя Webpack по таким критериям:
- Гибкость настройки
- Большое количество плагинов и лоадеров
- Lazy loading
- Использование es6 и es7 синтаксиса с помощью babel-loader
Из недостатков я бы выделил отсутствие ясной документации. Для тех, кто никогда не сталкивался с Webpack, я рекомендую скринкаст от Ильи Кантора. В данной статье хочу рассказать о настройках сборки проекта, написанного на React + Redux.
Я не буду углубляться в основы, а расскажу, какие плагины использую для сборки.
NoErrorsPlugin — это стандартный плагин Webpack, который не дает перезаписать скрипты при наличии в них ошибок. Это уберегает от уничтожения старой сборки как следствие нерабочего кода в продакшене. Подключается стандартно в массив с плагинами:
new webpack.NoErrorsPlugin()
EnvironmentPlugin — плагин для экспорта окружения в клиентских скриптах, что очень удобно для отладки и логирования. Подключение:
new webpack.EnvironmentPlugin("NODE_ENV")
Использование в коде:
var env = process.env.NODE_ENV;
DefinePlugin — плагин для объявления своих переменных при сборке. Например, для вырезания кусков кода общего конфига с сервером.
Подключение:
new webpack.DefinePlugin({
cutCode: JSON.stringify(true)
})
Использование:
if (typeof cutCode === 'undefined') {
// Ваш код
}
CommonsChunkPlugin — выносит общие библиотеки для чанков в отдельный чанк. Удобно для кеширования внешних библиотек и уменьшения веса чанков. Что такое чанки и Lazy loading доступно описано здесь. Подключение:
new webpack.optimize.CommonsChunkPlugin({
children: true,
async: true,
})
DedupePlugin — находит общие зависимости библиотек и обобщает их. Подключение:
new webpack.optimize.DedupePlugin()
UglifyJsPlugin — плагин, который сжимает скрипты. Параметры для этого плагина можно посмотреть здесь.
Подключение:
new webpack.optimize.UglifyJsPlugin({
// ваши настройки здесь
}
})
Мой вариант:
new webpack.optimize.UglifyJsPlugin({
beautify: false,
comments: false,
compress: {
sequences : true,
booleans : true,
loops : true,
unused : true,
warnings : false,
drop_console: true,
unsafe : true
}
})
OccurrenceOrderPlugin — плагин, который минимизирует id, которые используются webpack для подгрузки чанков и прочего. Подключение:
new webpack.optimize.OccurrenceOrderPlugin()
CompressionPlugin — сторонний плагин для компрессии скриптов, например, в gzip формат. Большинство браузеров принимает gzip файли при установлению в headers для ответа переменной Content-Encoding: gzip. Параметры здесь.
Установка:
npm install compression-webpack-plugin
Подключение:
CompressionPlugin = require("compression-webpack-plugin");
plugins: [
// твои плагины
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
]
WebpackShellPlugin — сторонний плагин для запуска команд до и после сборки. Например, для очистки старых файлов после сборки.
Установка:
npm install webpack-shell-plugin
Подключение:
new WebpackShellPlugin({
onBuildStart: ['echo "Webpack Start"'],
onBuildEnd: [
`node ./node_modules/clean-scripts-after-build --path ${__dirname + '/public/js/'} --bundleName bundle_${config.jsVersion}.js`
]
})
Отдельно хочу выделить подключение babel-loader. Он транспилит jsx, es6, es7 в es5 синтаксис.
Установка:
npm install babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-0
//babel плагины для минификации react компонент
npm install babel-plugin-transform-react-constant-elements
npm install babel-plugin-transform-react-inline-elements
npm install babel-plugin-transform-react-remove-prop-types
Подключение:
wpConfig = {
entry : ....,
output : {
//.......
}
module : {
loaders: [
{
loader : 'babel',
//не анализирует код в папке node_modules, там код уже переведен в es5 синтаксис
exclude: /node_modules/,
query: {
plugins: [
'transform-runtime',
'transform-react-remove-prop-types',
'transform-react-constant-elements',
'transform-react-inline-elements'
],
presets: ['es2015', 'stage-0', 'react'],
}
}
]
},
}
И да, не забудьте использовать окружение production. Код React и Redux написан так, что куски кода, которые не нужны в продакшене, вырезаются Webpack.
P.S. Я ужал свой бандл с 2.6 mb до 160 kb. Буду рад посмотреть все замечания, так как вариаций настройки может быть очень много.
Комментарии (2)
31 августа 2016 в 15:25
–1↑
↓
Вода!31 августа 2016 в 15:34 (комментарий был изменён)
+1↑
↓
А что не вода по webpack? Это моя первая статья, хотелось бы увидеть замечания поконкретней, если можно.