Webpack + React. Как уменьшить бандл в 15 раз

в 11:37, , рубрики: javascript, javascript webpack reactjs, node.js, ReactJS, метки:

image

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

Автор: BoryaMogila

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js