Вашему вниманию — Webpack 4

    Всем привет! На этот раз на повестке дня перевод статьи Valentino Gagliardi «Webpack 4 tutorial: All You Need to Know, from 0 Conf to Production Mode».

    image

    Команда разработчиков Webpack этот раз изрядно потрудилась над новым поколением популярного сборщика модулей (бандлера) — webpack 4.

    Репозиторий с используемым кодом здесь.

    Webpack 4 как сборщик модулей с нулевой конфигурацией


    Никто не спорит: у него есть мощные плюсы, большое количество возможностей и настроек, однако головной болью является файл конфигурации.

    Написание конфига не составляет проблемы для средних и больших проектов, без этого им трудно существовать. Тем не менее, небольшие проекты это может раздражать, особенно если хочется создать приложение-игрушку.

    Шон и команда webpack улучшили жизнь всем нам: webpack 4 больше не требует файла конфигурации по умолчанию!

    Что ж, протестируем.

    Создайте новую директорию и перейдите туда:

    mkdir webpack-4-quickstart && cd $_
    

    Инициализируйте package.json:

    npm init -y
    

    Теперь пускаем в бой webpack 4 (Версия сейчас находится в стадии beta, поэтому нужно добавить next):

    npm i webpack@next --save-dev
    

    Добавим webpack-cli, живущий своей жизнью в отдельном пакете:

    npm i webpack-cli --save-dev
    

    Открываем package.json и прописываем скрипт сборки:

    "scripts": { 
       "build": "webpack" 
    }
    

    Сохраните файл, закройте. Запустите:

    npm run build
    

    Что же случилось?

    ERROR in Entry module not found: Error: Can't resolve './src' in '~/webpack-4-quickstart'
    

    Webpack 4 ищет входную точку приложения ./src! Если не знаете, почему так получилось, то опишу вкратце: входная точка — это файл, с которого webpack начинает сборку. В ранних версиях нужно было объявить ее напрямую в webpack.config.js.

    Но начиная с 4-й версии вам не нужно указывать входную точку. Она будет взята из ./src/index.js по умолчанию!

    Проверим. Создайте ./src/index.js:

    console.log(`Можно я тут просто постою?`);
    

    Снова запустите сборку:

    npm run build
    

    Вы получите файл ~/webpack-4-quickstart/dist/main.js.

    Неужели нам не нужно задавать и точку выхода тоже? Именно! Ни точку входа, ни выхода. Тем более, не нужен файл конфигурации.

    Я знаю, что для большинства это неудивительно: сила webpack в разделении кода. Но поверьте: ноль конфигурации ускоряет разработку в разы.

    Режимы production и development


    image

    Очень часто можно встретить разделения конфига на несколько файлов.

    Типичный проект может иметь:

    • Конфигурацию для разработки (development), с webpack-dev-server и прочими игрушками разработчиков.
    • Конфигурация для продакшена с UglifyJSPlugin, source maps и другим.

    Пока крупные проекты продолжают использовать разделение конфигов, мы с webpack 4 сделаем все одной строкой.

    Как так? Встречайте режимы production и development.

    Если вы обратите внимание на вывод npm run build, то увидите красивую ошибку:

    image
    Опция ‘mode’ (режим) не была задана. Включите режим в ‘development’ или ‘production’, чтобы применить настройки по умолчанию.

    Что это значит? Будем разбираться. Откройте package.json и допишите объект скриптов, как показано ниже:

    "scripts": {
        "dev": "webpack --mode development",
        "build": "webpack --mode production"
      }
    

    И теперь попробуем:

    npm run dev
    

    Взглянем на ./dist/main.js. Что вы видите? Да, я знаю, скучный бандл… не уменьшен. А если:

    npm run build
    

    Что теперь? Файл сборки был уменьшен. Да! Режим ‘production’ использует все виды оптимизации самостоятельно. И там не только минимизация.

    С другой стороны режим разработчика (development mode) оптимизирует скорость приложения и ничего больше.

    Таким образом, с 4-м webpack’ом вы можете менять всю сборку одной строкой. Просто добавьте флажок --mode и получите результат совершенно безболезненно.

    Нравятся ли вам нововведения? Чего ожидаете от webpack в будущем? Пишите в комментариях.

    Спасибо за внимание.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 38

      +2
      А разве смысл webpack.config.js только в задании точек входа/выхода? :)
        0
        В данной статье описываются новые фичи. В дебри вебпака залезать не было смысла
          0
          В переопределении параметров по умолчанию. Теперь у точки входа и выхода есть значения по умолчанию, и переопределять их не обязательно
          0

          Список изменений впечатляет, жаль только, что с ExtractTextPlugin они не сильно спешат. Для веба это просто маст хэв, а текущая стабильная версия с новым webpack работать не может — API для плагинов сменили кардинально.


          Фича с указанием sideEffects выглядит весьма многообещающе. Очень надеюсь, что она наконец починит Tree shaking.

            0
            В оригинале для продакшена написано: Production mode enables all sorts of optimizations out of the box. Including minification, scope hoisting, tree-shaking and more.
            Не проверял, но хочется верить, что все работает
              0

              Вообще непонятно, почему ExtractTextPlugin не встроен в webpack из коробки. Я кое-как смирился с import './style.scss', но деплоить стили в виде гигантского строкового литерала в JS все ещё не готов. До сих пор хорошей практикой остается вставлять стили в head, а скрипты перед </body>.


              Но, может быть, нужда в нём отпадёт за счет того что 4.x будет поддерживать типы модулей html и css, то есть их не надо будет заворачивать в JS? Посмотрим

                0

                Если вас беспокоит style-loader как fallback для асинхронных чанков, то посмотрите в сторону ExtractCssPlugin. Он выносит весь css из всех чанков.
                Не уверен правда, что работает с webpack 4. Но на webpack 3 полёт нормальный.

                  0

                  Меня беспокоит, что такой фичи нету из коробки и надо танцевать с бубном. А менять один плагин на другой (кстати, я что-то так и не нагуглил ExtractCssPlugin) смысла особо не вижу — оба надо отдельно ставить и конфигурировать.

                    0

                    Немного название неправильно написал, вот он.


                    Ну конфигурация сверх лоадеров там всего несколько строчек


                    • вызов new Plugin({filename: 'mask'});
                    • pluginInstance.extract(loadersChain)

                    Да, отсутствие хорошей поддержки css из под коробки, конечно, немного смущает, тут не поспоришь.

                      0

                      Спасибо.


                      Что-то это по конфигу не сильно отличается… А в чем преимущество, что-то я туплю? Делает code split для css?

                        +2

                        Этот плагин по умолчанию для каждого асинхронного чанка создает свой css чанк. ExtractTextPlugin же выносит текст только из entry чанка.


                        Давайте рассмотрим на примере.
                        У вас есть чанки


                        • app.js — entry point
                        • common.js — получаемый из commonChunksPlugin
                        • mainPage.js — асинхронный чанк с функционалом главной страницы

                        В случае использования ExtractTextPlugin вы получите на выходе


                        • app.css — css entry поинта, которого будет не очень много
                        • common.js, mainpage.js — содержат стили внутри js'a через style-loader

                        В общем-то, в такой схеме ExtractTextPlugin не выглядит особо полезным.


                        ExtractCssChunksPlugin вообще не имеет опции fallback т.к. она ему не нужна, с помощью этого плагина вы получите следующую структуру:


                        • app.css — все тоже самое
                        • common.css — все общие стили
                        • mainPage.css — стили главной страницы

                        ExtractCssChunksPlugin — это ИМХО то, как должен работать ExtractTextPlugin по умолчанию.
                        Минусы этого плагина:


                        • Возможно не поддерживает webpack 4 (не проверял ещё)
                        • Дефолтное значение filename может мешать, уж много плагин на себя берёт этим значением, мог бы полагаться на то, что указано в секции output
                        • Он полагается на ExtractTextPlugin, и это видно в логах. Это само по себе не проблема. Если правильно помню структуру проекта, то проблема в том, что ExtractTextPlugin просто скопипащен (ctrl+c ctrl+v) внутрь ExtractCssChunks. Это, во первых, ужасно. Во вторых, можете забыть о получении фиксов\улучшений ExtractTextPlugin. Поэтому если встретите баг, который был исправлен в ExtractTextPlugin, вероятно он не будет исправлен в ExtractCssChunks.

                        Но мы используем ExtractCssChunks в продакшне и полёт пока ровный

                          0

                          Большое спасибо за подробное объяснение!

                        0
                        Да, отсутствие хорошей поддержки css из под коробки, конечно, немного смущает, тут не поспоришь.
                        В прошлом году нам обещали улучшенную поддержку:
                        https://medium.com/webpack/the-new-css-workflow-step-1-79583bd107d7

                        Но что-то с тех пор апдейтов не видно

                          0
                          We add a new module type to webpack: Stylesheet (next to Javascript)

                          Обещают в 4.x.

                  0
                  Собственно, потому стабильный релиз и состоится через месяц, чтобы разработчики плагинов могли подготовиться к интеграции с 4-й версией Webpack-а.
                  0

                  А что насчёт интеграции с бабелем?

                    0
                    В этом плане ничего не изменилось — можно брать старый конфиг и смело юзать
                    0
                    все ок, только sourcemaps — это не карты сайта :)
                      +1

                      Как насчёт обратной совместимости? В своё время, когда изучал Webpack, я столкнулся с проблемой: актуальной версией Webpack была 2, которая обратно-несовместимостима с версией 1 (плагины, написанные для версии 1 не работали с Webpack 2 и наоборот), а большая часть плагинов была написана для версии 1; приходилось ультимативно решать, какую версию Webpack использовать, и лучшим выбором являлась версия 1, потому что для неё было намного больше плагинов.

                        0
                        Не люблю черные ящики и котов в мешке, поэтому если в точке входа по умолчанию еще есть какие-то плюсы, то система сборки, которая использует «все виды оптимизации самостоятельно» вызывает разрадражение.

                        С другой стороны, если они подробно опишут в документации какие именно настройки применяются для каждого режима по умолчанию, и поддержат их точечное изменение (а заодно и то, чтобы можно было где-то глобально пложить собственные дефолты для каждого режима), то это реально поможет сократить простыню, которую приходится писать в конфиг…
                          +1

                          То есть киллер фича 4й версии это -2 строчки в конфиге?

                            –4
                            Разве это не прекрасно?!
                              0

                              А пропагандировалось как zero configuration

                                0
                                Это, как я понял, последние 2 строчки в конфиге, которые были обязательными раньше. То есть, в результате да — zero configuration.
                            –2
                            Детский сад
                              0

                              А что насчет http 2? Не отпадает ли надобность в вебпаке как таковом? Не судите строго просто прочитал где-то что с приходом http 2 сборка всего в один файл становится не нужной

                                0

                                Все равно нужен будет live/hot-reload, препроцессоры и минификация для продакшена (для мобильников это всё еще важно) — хотя возможно что этим будет заниматься уже не вебпак.

                                  0

                                  Ждем возвращение gulp?

                                    0

                                    Эту стюардессу не то что пора закопать, ей вообще не надо было рождаться:)

                                      0

                                      Хотя для сборки разного рода библиотек вебпак действительно прекрасен

                                +3

                                Весьма популярное заблуждение. Http2 не решает проблему, которую решает бандлинг.


                                Давайте представим ситуацию.
                                У вас есть точка входа, которая импортит класс приложения, который импортит еще модуль и так далее.
                                Думаю, вы без труда найдете в своем коде, например, 8 уровней импортов.


                                entry => application => rootComponent => component => anotherComponent => someLibrary => lodash.


                                Если отказаться от сборки исходников в один\несколько файлов, то возникает следующая ситуация.


                                • Браузер получает ваш entry point, узнает что ему нужен application
                                • Получает application, узнает, что нужен rootComponent
                                • и так далее до 8 уровня

                                Каждый шаг для браузера — это отдельный запрос со всеми вытекающими. http2 позволяет переиспользовать соединение, однако задержка между вами и пользователем, как ни крути, останется.
                                Если предположить, что задержка 50мс, то только 400мс уйдет на то, чтобы спросить у вас файлы (не учитывая скачивание, парсинг и всё такое). Если пользователь, не дай бог, с мобильного интернета, то там уже совсем другие цифры.


                                Решение у этой проблемы есть — сразу говорить пользователю, какие файлы ему понадобятся. Вместо того, чтобы собирать один\несколько файлов, нам теперь нужно строить граф зависимостей, чтобы оптимизировать отправку. Можно и из булки сделать троллейбус, но зачем? Воркфлоу без потерь не упрощается.


                                Ну и бонусом, бандлинг позволяет очень хорошо оптимизировать код (минификация, дедупликация, tree shaking, лучше гзипуется, легче пересылается по сети)

                                  0
                                  Ну по идее эту проблему решает http2 push. А как бонус не надо грузить ненужный код, и возможность кешировать ресурсы более рационально.
                                    +2
                                    Ну я про то и говорил.
                                    Чтобы сделать http2 push вам нужно знать, что пушить.
                                    Для того, чтобы знать, что пушить, вам нужен граф зависимостей, чтобы резолвнуть те модули, которые запросит пользователь. Не сказать, чтобы это сильно проще, но это решение, да. Также тут на хабре есть [статья](https://habrahabr.ru/company/badoo/blog/331216/), про то что пока не нужно использовать server push, браузеры его поддерживают по разному и нетривиально его сделать правильно. А если сделать неправильно, то пользователю будет плохо
                                    Ну и есть еще подводные камни, вот пара статей по этому поводу:
                                    * www.contentful.com/blog/2017/04/04/es6-modules-support-lands-in-browsers-is-it-time-to-rethink-bundling
                                    * engineering.khanacademy.org/posts/js-packaging-http2.htm
                                      +1

                                      -

                                    0
                                    каждый раз когда возникает желание посмотреть на http2 вспоминайте этот доклад www.youtube.com/watch?v=whFhyHysYYg
                                    0
                                    в целом ненавижу когда вместо гибких настроек и хорошей документации к ним с преднастроенным дефолным конфигом пытаются делать zeroConfig. Потом тебе надо что-то поменять и привет пол часа гугления, а иногда и дольше.
                                    Есть хороший принцип, простое — просто, сложное — возможно. Но на самом деле он не совсем полон, хорошо когда ещё и переход от простого к сложному происходит без переписывания кода или смены api. Или как в данном случае разумным считаю иметь преднастроенный дефолтный конфиг, с разделами где вписаны все настройки по умолчанию. И конфиг побит на разделы, типа base options, advanced options и expert. И тогда всё просто и понятно. И проще гуглить поведение каждой настройки.
                                      0
                                      warning !== error

                                      Only users with full accounts can post comments. Log in, please.