Изучите webpack менее чем за 10 минут

Что такое webpack?

Согласно официальной документации:

“webpack  —  это статический бандлер (инструмент для сборки модулей в единые пакеты) для современных приложений JavaScript.”

Как разработчики JavaScript, мы знаем, что такое модули, но в webpack они немного отличаются и состоят из:

  • Модулей ES  —  оператор import.
  • Общих модулей JS  —  оператор require().
  • Модулей AMD  —  операторы define и require.
  • Импортов CSS  —  оператор @import внутри любых файлов css/sass/less.
  • URL изображений  —  url(…) или <img src=”…” />.

webpack объединяет все эти различные модули таким образом, что можно импортировать все в код JavaScript.

Должен ли я изучать webpack?

Сегодня большинство приложений строится с использованием React/Vue или другой библиотеки. Они предоставляют инструменты CLI (например, create-react-app, @vue/cli), которые абстрагируют большинство конфигураций и предоставляют значения по умолчанию. Но так как рано или поздно хочется внести в них коррективы, необходимо понимать принципы их работы.

Начнем

Мы создадим простое приложение, чтобы продемонстрировать работу webpack. Создадим новый каталог и инициализируем проект npm. Находясь во вновь созданном каталоге, введите:

npm init -y

Установим необходимые пакеты webpack:

npm install --save-dev webpack webpack-cli webpack-dev-server

Откроем package.json, удалим уже существующий скрипт test и добавим новый dev для запуска webpack в режиме разработки. Этот скрипт удобен, когда мы работаем локально. Файл пакета должен выглядеть примерно так:

Теперь, если вы запустите npm run dev, получите ошибку: Entry module not found (Модуль ввода не найден). Это происходит потому, что по умолчанию webpack ожидает файл в src/index.js как точку входа. Кроме того, webpack по умолчанию выводит файлы сборки в каталог dist.

Исправим эту ошибку, создав новый каталог src и файл index.js. Введем console.log(‘hello’); в index.js.

Запустим npm run dev. Ошибок не будет, но вы найдете собранныйфайл main.js в каталоге dist.

Настройка webpack

Чтобы настроить webpack, нужно создать webpack.config.js внутри корневого каталога. В этом файле нужно экспортировать объект конфигурации. webpack работает в среде без интерфейса JavaScript, такой как Node.js.

Некоторыми из наиболее используемых терминологий являются:

  • Точка входа  —  указывает точку входа для webpack, из которой собираются все зависимости. Они образуют граф зависимостей.
  • Вывод  —  указывает, где в процессе сборки собираются результирующие JS и статические файлы.
  • Загрузчики  —  сторонние расширения, которые помогают webpack работать с различными расширениями файлов. Они преобразуют файлы, отличные от JS, в модули.
  • Плагины  —  сторонние расширения, которые могут изменить способ работы webpack.
  • Режим  —  определяет два режима: разработка и производство. По умолчанию это производство.

Настроим базовую точку входа и выходной каталог.

Изменение точки входа

Если нужно, чтобы webpack работал с source/index.js вместо папки src, заданной по умолчанию, нужно добавить свойство entry в экспортируемый объект:

Также можно использовать альтернативный синтаксис:

Изменение выходного каталога

Предположим, что мы хотим вывести встроенные файлы в каталог build, а не в dist, заданный по умолчанию. Можно использовать свойство output:

Включение собранного файла в HTML файл

В каждом веб-приложении есть по крайней мере один HTML-файл. Для работы с HTML нужно использовать плагин html-webpack-plugin. Начнем с установки:

npm install --save-dev html-webpack-plugin

Что делает этот плагин

Он загружает HTML-файлы и вводит бандл в тот же файл. Создадим простой HTML-файл и настроим его в конфигурации webpack.

Создадим index.html в каталоге source и вставим в него шаблонный код. Настроим это в файле webpack:

Поскольку файлы готовы, нужен сервер, который будет использоваться для их обслуживания. Используем webpack-dev-server, установленный ранее.

Сервер для webpack разработки

Чтобы настроить webpack-dev-server, нужно открыть package.json и добавить новый скрипт, который поможет запустить сервер. У нас есть dev, который нужен для сборки файлов. Создадим start, как показано ниже:

Выполните с терминала:

npm start

Перейдите в браузер и проверьте localhost:8080. Там будет index.html , вы можете открыть инструменты разработки и увидеть, что main.js из бандла также включен в него:

Файл main.js включен автоматически

Загрузчики webpack

Загрузчики в webpack  —  это сторонние расширения, которые имеют дело с другими расширениями файлов. Для webpack их доступно множество.

Перейдем к настройке загрузчиков в конфигурационном файле webpack. У них странный синтаксис. Мы используем ключ, называемый module, и он состоит из другого свойства, называемого rules, которое представляет собой массив загрузчиков. Для каждого файла, который мы хотим рассматривать как модуль, помещаем его как объект в массив rules. Каждый объект состоит из двух свойств: test определяет тип файла, а use —  это массив, состоящий из загрузчиков. Обратите внимание, что загрузчики, определенные здесь в use, загружаются справа налево. Порядок важен при определении загрузчиков. Перед их использованием обратитесь к документации.

Общий синтаксис загрузчика в конфигурационном файле выглядит следующим образом:

Работа с CSS

Для того, чтобы работать с CSS в webpack, нам нужны два загрузчика: CSS-loader и loader. Установим их с помощью:

npm install --save-dev css-loader style-loader

Создадим styles.css внутри каталога source. Добавим любые стили для отображения в index.html. Нужно включить этот файл в index.js, а не в index.html. Теперь index.js имеет вид:

Остается последний шаг. Настроить загрузчики в webpack.config.js. Конфигурационный файл должен выглядеть так:

css-loader используется для загрузки CSS-файлов, а style-loader  —  для загрузки таблицы стилей в DOM.

Когда вы перезагрузите сервер и запустите npm start, то увидите изменения:

Работа с SASS

Для работы с SASS (.scss) потребуются три загрузчика: sass-loader, css-loader и style-loader, а также дополнительный пакет sass, необходимый для Node. Здесь sass-loader используется для загрузки файлов SASS с импортом. Два их них установлены, доустановим остальные:

npm install --save-dev sass-loader sass

Создадим styles.scss в каталоге source и добавим в него эти строки или любые базовые стили:

Включим этот файл в index.js, используя import ‘./styles.scss’ прямо в его начале.

Теперь время добавить загрузчики в webpack.config.js. Загрузчик должен выглядеть так

Перезагрузим сервер и проверим изменения.

Работа с современным JavaScript

webpack сам по себе не знает, как преобразовать современный JavaScript в совместимый код, который может работать в любом браузере, поэтому он использует Babel. Установим следующие пакеты: @babel/core, который фактически и является движком; babel-loader  —  загрузчик, необходимый для webpack; и @babel/preset-env для преобразования JavaScript в ES5. Установим зависимости:

npm install --save-dev @babel/core babel-loader @babel/preset-env

Далее надо настроить Babel, создав babel.config.json в корневом каталоге. Мы настраиваем Babel на использование preset-envm, установленного ранее:

Добавим загрузчик, который мы установили для webpack.config.js:

Теперь используем ES6 и вышеприведенный синтаксис в JS-коде, и после повторной сборки с npm run dev мы сможем проверить собранный main.js и убедиться, что он автоматически транспилируется в браузерно-совместимый код.

Указание режимов в webpack

В webpack доступны два типа режимов: разработка и производство.

В режиме разработки нет минификации. webpack просто берет весь написанный JS-код и загружает его в браузер, тем самым ускоряя перезагрузку приложения.

В производственном режиме webpack применяет множество оптимизаций. Он автоматически использует минификацию с помощью terser-webpack-plugin для уменьшения размера бандла. Он также устанавливает значение process.env.NODE_ENV в production. Эта переменная полезна, поскольку мы можем в зависимости от условия выполнять разные вещи как в производстве, так и в разработке.

Чтобы использовать webpack в этом режиме, добавим еще один скрипт в package.json. Назовем его build. Скрипты должны выглядеть так:

Оптимизации  —  разделение кода

Разделение кода или ленивая загрузка  —  это метод оптимизации, позволяющий избежать больших бандлов, а точнее  —  дублирования зависимостей. Используя его, мы загружаем фрагмент кода по требованию, например, когда пользователь нажимает кнопку, когда меняется маршрут и т. д. Часть кода, который разделяется, называется фрагментом (chunk).

В webpack есть ограничение на максимальный размер файла исходного пакета приложения  —  меньше 244 КБ. Существует три способа добиться разделения кода в webpack:

  1. Наличие нескольких точек входа.
  2. Использование optimization.splitChunks.
  3. Динамический импорт.

Первый метод хорошо работает для небольших проектов, но не масштабируется в сложных. Мы указываем несколько точек входа в конфигурационный файл webpack.

optimization.splitChunks

Иногда мы используем много зависимостей в приложении. Например, популярный пакет для дат: Moment. Я выбрал его, потому что он тяжеловат по размеру. Установим его, а затем включим в index.js и выполним build:

npm install moment

Moment будет успешно установлен. Теперь импортируем его в index.js.

import moment from 'moment'

Запустим build:

npm run build

Увидим предупреждающее сообщение в терминале:

Слишком большой размер файла main.js

Как это решить? Все просто. Добавим ключ optimization и свойство splitChunks:

Размер точки входа значительно уменьшается.

Уменьшенный размер файла точки входа

Динамические импорты

Они используются для загрузки кода(в React и Vue, например) в зависимости от условия: на основе взаимодействия с пользователем либо изменения маршрута.

Для демонстрации добавим кнопку на страницу, которая по щелчку мыши извлекает список сообщений. Код для этой логики выборки присутствует в отдельном файле. Он импортируется динамически внутри index.js.

Вызовем API fetch отдельно в api.js в папке source. Здесь мы экспортируем функцию, которая делает запрос к общедоступному API и возвращает ответ:

Создадим кнопку в index.html со свойством id, равным btn:

<button id="btn">Click me to load</button>

Сделаем динамический импорт в index.js с помощью функции для импорта файла api.js:

const getTodos = () => import('./api')

Добавим логику для логирования извлеченных данных, добавив ее в конец файла:

const btn = document.getElementById('btn');btn.addEventListener('click', () => {
    getTodos().then(({fetchTodos}) => {
        fetchTodos().then(resp => console.log(resp))
    })
})

Этот фрагмент вызывает функцию getTodos, которая импортирует файл. Затем, мы разрушаем свойство fetchTodos, вызываем функцию и логируем ответ на ее успех.

Выполним сборку файлов, запустим сервер и обязательно откроем “инструменты разработки”, сохранив вкладку “сеть” открытой. Вы обнаружите, что при щелчке мыши появляется новый JS-файл, который загружается динамически:

Динамические импорты

0.main.js  —  это файл, который был загружен динамически. Для читаемого имени нужно добавить комментарий во время динамического импорта:

const getTodos = () => import(/* webpackChunkName: "postsAPI" */ './api')

Теперь, он загружает файл postsAPI.js , а не 0.main.js.

Еще любопытно?

Это краткое введение в webpack. Статья предназначена для начинающих разработчиков, которые хотят изучать webpack. В документации описано еще больше интересного.

Git  —  https://github.com/harshaktg/webpack-demo

Спасибо за чтение!

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Harsha Vardhan: Learn webpack in Under 10 Minutes

Предыдущая статьяМикрооптимизации в Java. Enum  -  хороший, красивый и медленный
Следующая статьяГалерея лучших модулей Python