Что такое 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
из бандла также включен в него:
Загрузчики 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:
- Наличие нескольких точек входа.
- Использование
optimization.splitChunks
. - Динамический импорт.
Первый метод хорошо работает для небольших проектов, но не масштабируется в сложных. Мы указываем несколько точек входа в конфигурационный файл webpack.
optimization.splitChunks
Иногда мы используем много зависимостей в приложении. Например, популярный пакет для дат: Moment. Я выбрал его, потому что он тяжеловат по размеру. Установим его, а затем включим в index.js
и выполним build
:
npm install moment
Moment будет успешно установлен. Теперь импортируем его в index.js
.
import moment from 'moment'
Запустим build
:
npm run build
Увидим предупреждающее сообщение в терминале:
Как это решить? Все просто. Добавим ключ 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
Спасибо за чтение!
Читайте также:
- Введение: 4 новейших операции JavaScript
- Сравниваем WebGL-фреймворки Three.js и Babylon.js
- Креативное программирование: методы и инструменты для JavaScript, Python и других языков
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Harsha Vardhan: Learn webpack in Under 10 Minutes