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

Комментарии (30)


  1. batya15
    31.08.2016 15:25
    +1

    Вода!


    1. BoryaMogila
      31.08.2016 15:34
      +3

      А что не вода по webpack? Это моя первая статья, хотелось бы увидеть замечания поконкретней, если можно.


      1. 13luck
        31.08.2016 16:10
        +2

        Расскажите, пожалуйста, что-нибудь про tree-shaking в webpack.


        1. BoryaMogila
          31.08.2016 16:16

          tree-shaking доступно только для webpack 2. Буду переходить на второй, напишу похожую статью


        1. Dreyk
          31.08.2016 17:38

          я собственно зашел в статью только ради того, чтоб почитать про tree-shaking...


          Сама по себе статья неплоха, но советую переходить на webpack2, уже можно, есть совместимые версии react-hot-loader и webpack-dev-server


      1. iLikeKoffee
        31.08.2016 16:25
        +2

        Нормальная статья, не обращайте внимания. Особенно, с учетом того, что материала по теме на русском кот наплакал. У меня, кстати, есть boilerplate для проектов на react + redux (с webpack, сборкой, минификацией и т.д.). Однозначно, почерпну у вас пару приемов.


        1. BoryaMogila
          31.08.2016 16:28

          Спасибо


  1. lagun4ik
    31.08.2016 16:03

    Есть еще очень классная штука — babel-react-optimize


    1. BoryaMogila
      31.08.2016 16:04

      Обезательно посмотрю, спасибо.


  1. vovkvlad
    31.08.2016 16:04

    Я выбрал для себя Webpack по таким критериям:
    • Использование es6 и es7 синтаксиса с помощью babel-loader



    Не то что бы я придирался, просто, насколько мне известно, то возможность подключить babel есть почти во всех сборщиках (если не во всех), потому сразу бросился в глаза данный пункт в сторону выбора webpack-a


    1. BoryaMogila
      31.08.2016 16:06

      Согласен у многих есть, мне понравилось удобство подключения. Но у многих и нету.


      1. hell0w0rd
        01.09.2016 01:07

        Но у многих и нету.

        Например?


        1. BoryaMogila
          01.09.2016 01:21

          babel можно прекрутить куда угодно, вопрос стоит в удобсве натройки и предпочтении разработчика.


          1. hell0w0rd
            01.09.2016 01:31

            таки куда угодно. А где неудобно настраивать? Вроде везде babelrc поддерживается одинаково, не?


        1. kashey
          01.09.2016 11:47

          В https://github.com/yandex/ymb никакого бабеля нету, как и возможности использовать es2015 модули.
          А сам сборщик не плохой, особенно в плане минимизации передачи данных.


  1. agabidullin
    31.08.2016 16:06
    +6

    Статья именуется «Webpack + React. Как уменьшить бандл в 15 раз». Под катом — список плагинов и "...P.S. Я ужал свой бандл с 2.6 mb до 160 kb".
    Как-то не связано получилось. Хотелось бы прочесть историю от начала до конца: как подключается webpack, как работает и т.п.
    Либо стоит поменять название статьи на «Какие плагины я использую для webpack»


    1. BoryaMogila
      31.08.2016 16:12
      -3

      Имеется ввиду, что используя эти плагины можно уменьшить размер бандла в 15 раз.


      1. remnev
        31.08.2016 16:39
        +4

        Как NoErrorsPlugin, EnvironmentPlugin, WebpackShellPlugin, babel-loader помогают уменьшить размер бандла в 15 раз?


        1. magmoro
          31.08.2016 16:55
          +1

          вообще никак, к уменьшению никакого отношения не имеют


        1. BoryaMogila
          31.08.2016 16:59
          -3

          Я согласен не имеют, изначально планировалась статья с названием типа «webpack для продакшн зборки».


  1. Laney1
    31.08.2016 16:43

    библиотеки вроде react можно вообще не включать в бандл, а загружать отдельно из CDN


    1. BoryaMogila
      31.08.2016 16:56

      Можно, но опасно при збоях работы CDN.


  1. magmoro
    31.08.2016 16:55
    +1

    кстати есть интересная статья, правда не про реакт, а ангуляр 2 уменьшение кода до 20кб (1.6mb без компресии и минификации) http://blog.mgechev.com/2016/07/21/even-smaller-angular2-applications-closure-tree-shaking/ используя precompiled templates, tree shaking, google closure compiler и brotli (вместо gzip, хотя brotli не все браузеры поддерживают).


    1. BoryaMogila
      31.08.2016 17:00

      спасибо, прочту.


  1. shir
    31.08.2016 16:59

    Из недостатков я бы выделил отсутствие ясной документации. Для тех, кто никогда не сталкивался с Webpack, я рекомендую

    Немножко устаревший туториал, но узнал много полезного. http://survivejs.com/webpack/introduction/


    1. BoryaMogila
      31.08.2016 17:01

      устаревший, но понятный. Лутше пока не встречал.


  1. alemiks
    31.08.2016 22:35

    если ещё выкинуть реакт и вместо него преакт, то можно еще раз в 5 уменьшить )


  1. BoryaMogila
    31.08.2016 22:50

    я думаю что профита будет не много так как реакт весит около 50 kb. Это до gzip. Тем более что все варнинги console.log и прочие вещи выкидеваются при зборке. Хотя заменить на преакт не пробовал, наверняка утверждать не могу.


    1. seokirill
      07.09.2016 12:38

      Расскажите глупому, что за перекат оО?!


  1. BoryaMogila
    07.09.2016 19:08

    Преакт, минифицированый реакт