Наверно, уже каждый разработчик хотя бы мало-мальски интересующийся новостями в своей профессиональной сфере слышал про webpack. Что это за зверь, и для чего он нужен, мы с вами разберём сегодня?
Начнём с определения. Webpack — это невероятно мощный, гибкий и популярный сборщик модулей JavaScript. Он уже успел не раз удивить JS-сообщество своими возможностями, завоевав сердца многих разработчиков.
Вся конфигурация Webpack представляет из себя обычный CommonJS-модуль, расположенный в файле webpack.config.js
. Для того, чтобы познакомиться с этим инструментом, необходимо понимать базовые термины и концепции, лежащие в его основе, четыре кита, на которых всё держится. Верхнеуровневых понятий, на которых всё это работает, всего четыре: точка входа (Entry), место назначения, куда будет производиться вывод результатов (Output), загрузчики (Loaders) и плагины (Plugins). Расскажу о каждом из них подробнее.
Точка входа (Entry)
В ходе своей работы Webpack строит граф всех зависимостей нашего приложения. Начало этого графа и называют точкой входа (entry point). Эта точка говорит Webpack, откуда начинать обход графа зависимостей, чтобы собрать всё в один bundle — результат сборки модулей в один файл. Точкой входа можно считать тот самый файл, который надо дёрнуть, чтобы ваше приложение заработало.
Указать точку входа можно при помощи свойства entry
в объекте конфигурации webpack.
module.exports = {
entry: './app/index.js'
};
Помимо этого способа указания точки входа есть и другие, но мы сейчас углубляться в такие подробности не будем.
Вывод результата (Output)
Как только мы собрали все, что хотели, в один пакет, возникает необходимость где-то это всё разместить. Для этого надо указать свойство webpack-конфигурации output
, которое показывает, где и как располагать результат сборки.
var path = require('path');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'my-bundle.js'
}
};
В этом примере через свойства output.filename
и output.path
мы говорим webpack, в какой bundle и в какой директории выгрузить получившийся код нашего приложения.
Конечно, в конфигурации вывода может быть указано гораздо больше параметров, но для нашего знакомства этого пока достаточно.
Загрузчики (Loaders)
Наша цель — чтобы все статические файлы в нашем проекте стали заботой webpack’а, а не браузера. Но это не значит, что все они должны быть объединены в один файл. Webpack обрабатывает каждый файл (.css, .html, .scss, .jpg и т.д.) как модуль. При этом сам webpack понимает только JavaScript.
Загрузчики webpack трансформируют эти файлы в модули согласно тому, как они добавлены в граф зависимостей. По своей сути, загрузчики — это трансформации, которые производятся над ресурсом зависимости вашего приложения. Они представляют из себя функции, запускаемые на NodeJS, принимающие на вход в качестве параметра содержимое файла зависимости и возвращающие новое содержимое.
На самом верхнем уровне у загрузчиков есть две задачи:
- Определить файлы, которые следует трансформировать этим загрузчиком, с помощью свойства
test
; - Трансформировать этот файл так, чтоб он мог быть добавлен в наш граф зависимостей и, в конечном счёте, в наш bundle, с помощью свойства
use
.
var path = require('path');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'my-bundle.js'
},
module: {
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
}
};
В этой конфигурации мы определили правило в соответствующем списке правил модуля с двумя обязательными свойствами: test
и use
. Это говорит webpack-компилятору примерно следующее:
«Привет, компилятор Webpack! Если ты при просмотре моего кода вдруг повстречаешь пути, в которых содержатся файлы с расширением ‘.js’ или ‘.jsx’ внутри вызовов require()
или в выражении import
, используй, пожалуйста, babel-loader для того, чтоб трансформировать его перед добавлением в сборку. Спасибо, друг!»
Важно помнить, когда определяете правила в конфиге webpack, что определять их нужно в module.rule, а не в rules. Если вы сделаете это неправильно, webpack будет на вас орать и ругаться красными буквами.
Конечно, настройка загрузчиков этими свойствами не ограничивается. Но давайте перейдём к плагинам.
Плагины (Plugins)
Поскольку загрузчики выполняют только трансформацию и только по каждому файлу в отдельности, плагины чаще всего используются (но этим не ограничиваются) в операциях и специальной функциональности над «компиляциями» или «кусочками» наших собранных модулей. Webpack’овская система плагинов очень мощна и хорошо настраиваема.
Чтобы использовать плагин, нам нужно только получить его через require()
и добавить в массив плагинов. Большинство плагинов можно настроить с помощью опций. Поскольку мы можем использовать плагин несколько раз в одной конфигурации для разных целей, нам нужно создать его экземпляр, вызвав его с оператором new
.
const HtmlWebpackPlugin = require('html-webpack-plugin'); // устанавливается отдельно через npm
const webpack = require('webpack'); // для доступа к встроенным плагинам
const path = require('path');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'my-bundle.js'
},
module: {
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './app/index.html'})
]
};
В webpack есть встроенные плагины! Посмотреть их можно на странице «Plugins» в официальной документации.
Использование плагинов в нашей конфигурации выглядит очень простым, но бывает много сценариев использования, в которых всё гораздо менее тривиально.
Заключение
Вот и всё! Мы с вместе вами познакомились с webpack, разобрались в его основных концепциях, увидели примеры конфигурации и попробовали простые случаи использования. Как вы видите, ничего в webpack страшного нет, всё достаточно просто! Поэтому не бойтесь и не ленитесь! Берите на своё вооружение этот новый для вас инструмент, учитесь, и вы увидите, что спектр его возможностей очень широк!
До новых статей!