Что такое Webpack?
Webpack — это инструмент, позволяющий скомпилировать, например, JavaScript модули в единый JS-файл. Webpack также известен как сборщик модулей.
При большом количестве файлов он создает один объемный файл (или несколько файлов) для запуска вашего приложения.
Он также способен выполнять множество иных операций:
- помогает собрать воедино ваши ресурсы
- следит за изменениями и повторно выполняет задачи
- может выполнить транспиляцию JavaScript следующего поколения до более старого стандарта JavaScript (ES5) с помощью Babel, что позволит использовать новейшие функции JavaScript, не беспокоясь о том, поддерживает их браузер или нет
- может выполнить транспиляцию CoffeeScript в JavaScript
- может конвертировать встроенные изображения в data:URI
- позволяет использовать require() для CSS файлов
- может запустить webpack-dev-server (в нём встроен локальный сервер и livereload (“живая перезагрузка браузера”))
- может работать с Hot Module Replacement (замена горячего модуля)
- может разделить выходной файл (output file) на несколько файлов, чтобы избежать медленной загрузки страницы из-за большого размера JS-файла
- может выполнить Tree Shaking
Webpack не ограничивается одним лишь фронтендом, его также успешно применяют в бэкенд разработке на Node.js.
У Webpack есть предшественники, у которых он перенял многие идеи. Основное различие заключается в том, что те инструменты известны как task runners (такс-раннеры), в то время как Webpack ничто иное, как сборщик модулей.
Webpack — это более целенаправленный инструмент. Вам достаточно указать точку входа в ваше приложение (это может быть даже HTML-файл с тегами <script>), а webpack проанализирует файлы и объединит их в один выходной JavaScript-файл, содержащий все необходимое для запуска приложения.
Установка Webpack
Webpack может быть установлен глобально или локально для каждого проекта.
Глобальная установка
Глобальная установка с помощью Yarn:
yarn global add webpack webpack-cli
с помощью npm:
npm i -g webpack webpack-cli
Теперь мы можем запустить webpack:
webpack-cli
Локальная установка
Это рекомендуемый способ установки, поскольку Webpack может обновляться каждый проект и у вас возникнет меньше проблем при использовании последних функций для одного небольшого проекта, нежели постоянное обновление всех проектов, в которых используется Webpack.
Установка с помощью Yarn:
yarn add webpack webpack-cli -D
с помощью npm:
npm i webpack webpack-cli --save-dev
После этого добавьте эти строчки в свой package.json
файл:
{
//...
"scripts": {
"build": "webpack"
}
}
Как только все будет сделано, вы можете запустить Webpack, набрав:
yarn build
в корневом каталоге проекта.
Настройка Webpack
По умолчанию, Webpack (начиная с 4-й версии) не требует никакой настройки, если вы соблюдаете эти правила:
- точкой входа вашего приложения является
./src/index.js
- вывод (output) размещается в
./dist/main.js
- Webpack работает в production mode (режим производства)
Конечно, если понадобится, вы сможете настроить каждую мельчайшую деталь в Webpack. Конфигурационный файл Webpack —webpack.config.js
хранится в корневой директории проекта.
Точка входа
По умолчанию, точкой входа является ./src/index.js
. Нижеприведенный пример использует файл ./index.js
в качестве входной точки.
module.exports = {
/*...*/
entry: './index.js'
/*...*/
}
Вывод (output)
По умолчанию, вывод размещается в ./dist/main.js
. В нижеприведенном примере, результат работы в Webpack генерируется в файле app.js
:
module.exports = {
/*...*/
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
}
/*...*/
}
С помощью Webpack можно использовать оператор import
или require
в своем JavaScript коде для того, чтобы подключать файлы любого типа (например, CSS).
В Webpack загрузчики являются аналогами задач (tasks) в Grunt и Gulp. Они принимают содержимое файлов, а затем преобразуют его необходимым образом и включают результат преобразования в общую сборку. Например, они могут компилировать TypeScript, загружать компоненты Vue.js и многое другое.
Например, в своем коде вы можете использовать:
import 'style.css'
указав конфигурацию данного загрузчика в файле webpack.config.js
:
module.exports = {
/*...*/
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
}]
}
/*...*/
}
Регулярное выражение применяет данный загрузчик только к CSS файлам.
У загрузчика есть параметры:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
/*...*/
}
Для одной и той же задачи может потребоваться несколько загрузчиков:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.css$/,
use:
[
'style-loader',
'css-loader',
]
}
]
}
/*...*/
}
В этом примере css-loader
интерпретирует директиву import 'style.css'
в CSS. Затем style-loader
внедряет этот CSS в DOM, используя тег <style>
.
Порядок выполнения перевернут (последнее выполняется первым).
Так сколько всего существует загрузчиков? Очень много! Здесь вы сможете найти полный список.
Самым часто используемым загрузчиком является Babel — он используется для транспиляции современного JavaScript в ES5:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
/*...*/
}
Данный пример заставляет Babel предварительно обрабатывать все наши React/JSX файлы:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
resolve: {
extensions: [
'.js',
'.jsx'
]
}
/*...*/
}
Здесь вы можете увидеть параметры babel-loader
.
Плагины
Плагины — это почти то же самое, что и загрузчики, но под стероидами. Они могут сделать то, что не могут загрузчики. Ко всему прочему, Webpack построен на системе плагинов, которые вы используете в своем файле конфигурации.
Рассмотрим следующий пример:
module.exports = {
/*...*/
plugins: [
new HTMLWebpackPlugin()
]
/*...*/
}
Плагин HTMLWebpackPlugin
автоматически создает HTML-файл с уже подключенным скриптом.
Здесь доступно множество плагинов.
Еще один полезный плагин,CleanWebpackPlugin
, мы можем использовать перед перегенерацией файлов, чтобы очистить нашу папку dist/
и получить аккуратный файл с конфигурацией.
module.exports = {
/*...*/
plugins: [
new CleanWebpackPlugin(['dist']),
]
/*...*/
}
Режимы Webpack
Данные режимы (появившиеся в 4-й версии Webpack) настраивают среду, в которой будет работать Webpack. Режим может быть настроен на development
или production
(по умолчанию стоит production
).
module.exports = {
entry: './index.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
}
}
Режим development
:
- менее оптимизирован, чем
production
- работает быстрее
- не удаляет комментарии
- предоставляет более подробные сообщения об ошибках и способы их решения
- сильно облегчает отладку
Режим production
работает медленнее, чем development
, так как ему нужно создать более оптимизированный бандл. Полученный JavaScript файл меньше по размеру, поскольку многое из режима development
в нем отсутствует.
Я написал небольшое приложение, которое выводит содержимое console.log
.
Вот бандл production
:
Вот бандл development
:
Запуск Webpack
Если Webpack установлен глобально, его можно вручную запустить из командной строки. Но, обычно, вы прописываете скрипт внутри файла package.json
, который затем запускаете через npm
или yarn
.
Например, эти package.json
скрипты, которые мы использовали ранее:
"scripts": {
"build": "webpack"
}
позволяют запускать webpack
, набрав:
npm run build
или:
yarn run build
или просто:
yarn build
Просмотр изменений
Webpack может автоматически перестраивать бандл, когда в вашем приложении происходят изменения. Для этого добавьте данный скрипт:
"scripts": {
"watch": "webpack --watch"
}
и запустите данную функцию:
npm run watch
или:
yarn run watch
или просто:
yarn watch
Одной из приятных особенностей watch mode (режима просмотра) является то, что бандл изменяется только в том случае, если в сборке нет ошибок. Если ошибки присутствуют, watch
продолжит следить за изменениями и будет пытаться перестраивать бандл, но текущий, рабочий бандл не зависит от проблемных бандлов.
Обработка изображений
С помощью Webpack можно очень удобно работать с изображениями, используя загрузчик file-loader
.
Эта простая конфигурация:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
]
}
/*...*/
}
Позволяет импортировать изображения в ваш JavaScript:
import Icon from './icon.png'
const img = new Image() img.src = Icon element.appendChild(img)
Где img
— это HTMLImageElement. Ознакомьтесь с документацией по Image().
file-loader
может обрабатывать и другие типы ассетов, например, шрифты, CSV-файлы, XML и т.д.
Еще одним приятным инструментом для работы с изображениями является url-loader
загрузчик.
В этом примере загружается любой PNG-файл размером менее 8 КБ в качестве data:URL.
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.png$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
/*...*/
}
Обработайте SASS код и преобразуйте его в CSS
Используйте sass-loader
, css-loader
и style-loader
:
module.exports = {
/*...*/
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
/*...*/
}
Генерация Source Maps
С транспилированным кодом, зачастую, возникают проблемы при отладке кода в браузере или анализе ошибок. Так как транспилированный и трудночитаемый JavaScript, а не оригинальный код, затрудняет поиск и исправление ошибок. Source Map — это JSON-файл, который содержит информацию о том, как транспилировать код обратно в исходный код.
Source Maps можно сгенерировать, используя свойство конфигурации devtool
:
module.exports = {
/*...*/
devtool: 'inline-source-map',
/*...*/
}
devtool
имеет множество возможных значений, из которых наиболее часто используемые:
none
: не добавляет Source Mapssource-map
: идеально подходит для режимаproduction
, предоставляет отдельную Source Map, которую можно свернуть и добавляет ссылку в бандл, чтобы инструменты разработки знали о том, что Source Map доступнаinline-source-map
: идеально подходит для режимаdevelopment
, встраивает Source Maps в качестве data:URL
Перевод статьи Flavio Copes: A beginner’s introduction to Webpack