
Ясной инструкции по сборке 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. Буду рад посмотреть все замечания, так как вариаций настройки может быть очень много.