Когда-то веб-сайты состояли из HTML- и CSS-файлов, а иногда ещё из одного или нескольких файлов JavaScript. Но с появлением JavaScript-модулей веб-сайты стали сложнее и их стало труднее поддерживать — нужно следить за всеми зависимостями, конфликтами между скриптами и тем, чтобы всё вместе это хозяйство работало без ошибок. Для этого стали использовать инструменты сборки. Сегодня об одном из таких — сборщике Webpack.
Что такое сборщик Webpack
Webpack — это инструмент для объединения данных из разных источников, например JS, TS, CSS, фреймворков и библиотек. Webpack берёт их, настраивает и объединяет в один итоговый файл — пакет ресурсов сайта. Этот файл можно оптимизировать разными способами, например для уменьшения размера, отложенной загрузки и так далее. Файл собирается на компьютере разработчика, а не на стороне сервера или браузера — они работают только с результатом: сервер отправляет файл браузеру, а тот отображает страницу или веб-приложение.
Работа сборщика на простом примере
Возьмём пример любого веб-приложения, которое состоит из index.html со ссылками на множество тегов скриптов:
<body>
...
<script src='./src/blog.js'></script>
<script src='./src/about.js'></script>
<script src='./src/contact.js'></script>
<script src='./src/index.js'></script>
</body>
Здесь скрипты подключаются вручную в том порядке, в котором они написаны. Так можно, но иногда есть проблемы:
- Скрипты надо подключать в правильном порядке. Если так не сделать, первый скрипт будет загружаться раньше второго, на чью функцию ссылается первый. В примере выше скрипты blog.js, about.js и contact.js должны быть загружены в браузер раньше, чем index.js, который ссылается на их функции.
- При ручном вводе могут быть ошибки или опечатки, и страница не отработает правильно все скрипты. От этого может поехать вёрстка и содержимое.
- При скачивании всех указанных скриптов и их зависимостей по отдельности происходит большое количество сетевых запросов для каждого скрипта. Это создаёт нагрузку на сервер, замедляет загрузку страницы в браузере и плохо масштабируется.
При использовании сборщика эти проблемы решаются автоматически, с ним можно не беспокоиться о включении каждого тега скрипта в нужный момент и в нужном порядке. Вместо набора тегов в коде будет всего одна строка (bundle.js — это как раз итоговый файл, результат работы сборщика):
<body>
...
<script src="./dist/bundle.js"></script>
</body>
Как установить Webpack
Самый простой способ установить Webpack — использовать менеджер пакетов. На компьютере должен быть установлен Node.js и готовый файл package.json:
{
"name": "webpack-5-examples",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
},
"repository": {},
"keywords": [],
"devDependencies": {
"@types/webpack": "^5.28.0",
"@types/core-js": "^2.5.5",
"@types/node": "^17.0.18",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.5.1",
"path": "^0.12.7",
"postcss": "^8.4.6",
"sass": "1.49.7",
"sass-loader": "^12.6.0",
"ts-loader": "^9.2.6",
"ts-node": "^10.7.0",
"typescript": "^4.6.2",
"vue": "^3.2.31",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0",
"webpack-nano": "^1.1.1",
"webpack-node-externals": "^3.0.0"
}
}
Лучше всего устанавливать Webpack так, чтобы у всех работающих над проектом была одна и та же его версия.
npm install webpack --save-dev
После установки Webpack нужно запустить его через скрипт Node.js. Для этого в package.json нужно добавить такие строки:
//...
"scripts": {
"build": "webpack -p",
"watch": "webpack --watch"
},
//...
Опция -p
минимизирует связанный код. Теперь для сборки наших файлов с помощью Webpack достаточно вызвать процесс в терминале с помощью такой команды:
npm run build
А эта команда запустит процесс сборки, при котором наши файлы будут автоматически объединяться при изменении любого из них:
npm run watch
Последняя часть настройки состоит в том, чтобы указать Webpack, какие файлы ему следует объединить. Рекомендуется делать это с помощью файла конфигурации.
Как создать файл конфигурации Webpack
Мы сделаем самую простую конфигурацию, просто чтобы показать, как это всё работает. Но на практике файлы конфигурации Webpack могут быть большими и отличаться друг от друга в разных проектах.
Начнём с того, что добавим файл с именем webpack.config.js в корневой каталог нашего проекта. В этом файле мы даём Webpack набор команд, чтобы он знал, что делать с файлами нашего проекта и как объединить их так, как мы хотим их использовать:
var path = require('path');
module.exports = {
entry: './assets/js/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Параметр entry
сообщает Webpack, какой из файлов JavaScript является нашим основным файлом, это ещё называют точкой входа. Её можно задать и другими способами, но в большинстве случаев достаточно одной записи.
С помощью параметра output
мы указываем имя и путь к нашему итоговому сборному файлу. После запуска Webpack весь наш JavaScript будет храниться в файле bundle.js. Он и будет тем одним файлом скрипта, который мы свяжем с нашим файлом HTML.
<script src="./dist/bundle.js"></script>
Этой настройки достаточно, чтобы начать работу с Webpack. Позже мы добавим в него кое-что ещё, но сперва посмотрим, как работают модули.
Модули Webpack
С модулями Webpack можно работать по-разному, так что вы можете использовать тот способ, который вам нравится. Мы будем использовать синтаксис import.
Представим, что нам нужно добавить модуль, который будет приветствовать пользователей нашего веб-приложения. Для этого мы создадим файл greeter.js и экспортируем из него такую функцию:
function greet() {
console.log('Горячо приветствуем наших любимых читателей и желаем хорошего настроения!');
};
export default greet;
Чтобы использовать этот модуль, нужно импортировать его и вызвать в нашей точке входа. Напомним, что мы указали в качестве неё index.js в файле конфигурации.
В результате работы Webpack наша точка входа и модуль приветствия были собраны в один файл bundle.js. Если изобразить их последующую работу на схеме, получится такая:
Как использовать библиотеки
Представим, что нам нужно, чтобы наше веб-приложение приветствовало пользователя, указывая конкретный день недели. Для этого мы используем модуль moment.js, импортировав его в наш модуль приветствия.
Сначала установим библиотеку через npm:
npm install moment --save
Теперь импортируем библиотеку в наш модуль приветствия greeter.js точно так же, как импортировали локальные модули выше:
import moment from 'moment';
function greet() {
var day = moment().format('dddd');
console.log('Have a great ' + day + '!');
};
export default greet;
Схема взаимодействия и обработки файлов немного усложнилась:
Как использовать загрузчики
Загрузчик — это способ, которым Webpack выполняет задачи во время объединения и предварительной или последующей обработки файлов. Например, загрузчики могут компилировать TypeScript, загружать компоненты Vue.js, отображать шаблоны и так далее.
Представим, что мы хотим добавить в наш проект проверку JS-кода на ошибки. Мы можем сделать это, включив загрузчик JSHint, который выявляет различные неисправности в коде.
Чтобы использовать JSHint, нужно установить его и его загрузчик Webpack:
npm install jshint jshint-loader --save-dev
Теперь добавим несколько строк в наш файл конфигурации Webpack webpack.config.js. Они запустят загрузчик и сообщат ему, какие типы файлов проверять, а какие нет:
var path = require('path');
module.exports = {
entry: './assets/js/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
// Добавляем модуль загрузчика JSHint
module: {
rules: [{
test: /\.js$/, // Запускаем загрузчик для всех файлов .js
exclude: /node_modules/, // Игнорируем все файлы в папке node_modules
use: 'jshint-loader'
}]
}
};
Смотрите хитрость: так как moment.js, который проверяет день недели, находится в папке node_modules, он не будет проверяться загрузчиком JSHint. Теперь схема взаимодействия и работы наших файлов выглядит так:
Что дальше
В следующий раз мы создадим настоящий проект с помощью Webpack, объединив несколько скриптов, и посмотрим, как это выглядит в жизни. Подпишитесь, чтобы не пропустить продолжение.