Статья/презентация изначально доступна в моем девблоге.

Webpack, вероятно, сейчас является самым спорным инструментом во внешнем веб-интерфейсе. Это самый популярный сборщик модулей, но многим новым пользователям трудно его использовать.

Я считаю, что одна из причин этого заключается в том, что способ работы webpack сильно отличается от инструментов, которые ему удалось выкорчевать (например, gulp). Проблема усугубляется тем фактом, что файлы конфигурации веб-пакетов, как правило, довольно сложны на первый взгляд, и случайное копирование и вставка его частей в надежде, что конфигурация будет работать только в вашем собственном проекте, может привести к катастрофе.

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

  • Новое в вебпаке
  • Запутайтесь в том, как именно работает Webpack
  • Не видите преимуществ (и недостатков) Webpack по сравнению с другими инструментами, такими как Gulp или Grunt.

Тогда эта статья может быть для вас.

Это простая веб-страница

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link href="css/main.css" rel="stylesheet" type="text/css">
  <title>Sample</title>
</head>
<body>
  <div>Sample</div>
  <script src="js/main.js"></script>
</body>
</html>

Конечно, мы редко пишем такие простые страницы. Обычно у нас есть дополнительные css и javascript. Со временем мы можем добавить некоторые пользовательские виджеты js, которые, в свою очередь, зависят от другой библиотеки, поэтому мы также вставляем ее на страницу.

К сожалению, с несколькими зависимостями наш HTML-файл быстро становится громоздким:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link href="css/main.css" rel="stylesheet" type="text/css">
  <title>Sample</title>
</head>
<body>
  <div><!-- One long DOM --></div>
  <script src="js/jquery.js"></script>
  <script src="js/menu-widget.js"></script>
  <script src="js/menu-widget--fancy-button.js"></script>
  <script src="js/ad-widget.js"></script>
  <script src="js/loading-bar.js"></script>
  <script src="js/loading-bar.fancy.theme.js"></script>
  <script src="js/social.sdk.js"></script>
  <script src="js/analytics.js"></script>
  <script src="js/analytics.seo.js"></script>
  <script src="js/main.js"></script>
</body>
</html>

Есть куча причин, почему приведенный выше код плохой

  1. Много JS-файлов в тегах script означает много сетевых запросов. Это приводит к замедлению времени загрузки (но будет решено HTTP/2).
  2. Есть неявные зависимости. Хотя menu-widget--fancy-button загружается так же, как и любой другой скрипт, на самом деле он зависит от menu-widget, который, в свою очередь, зависит от jquery. Насколько нам известно, это также зависит от loading-bar — мы не знаем, пока не посмотрим на код/документацию.
  3. В связи с вышеизложенным существует неявный порядок загрузки. main.js не может быть помещен сверху, так как он должен выполняться после того, как все остальные скрипты, на которые он опирается, загрузятся.
  4. Все глобально (или, по крайней мере, более вероятно)

Первая проблема решается конкатенацией — мы получаем все наши javascript-файлы и объединяем их в один javascript-файл. Это то, для чего предназначено большинство препроцессоров/исполнителей задач (изображение, ворчание, глотание).

Сделать что-то подобное с помощью Webpack невероятно просто.

Предполагая, что вы установили веб-пакет с npm install webpack -g, вы можете создать объединенный пакет, написав webpack [your files] [output name]. Используя наш пример выше, мы пишем:

webpack js/jquery.js js/menu-widget.js [...] output.js

Где [...] — это остальные ваши файлы (например, js/menu-widget--fancy-button.js js/ad-widget.js и т. д.)

Вход

jquery.js
menu-widget.js
menu-widget--fancy-button.js
ad-widget.js
loading-bar.js
loading-bar.fancy.theme.js
social.sdk.js
analytics.js
analytics.seo.js
main.js

Вывод

output.js

Конечно, писать все имена файлов, которые мы хотим объединять каждый раз, когда мы вносим изменения, становится утомительно. К счастью, мы можем создать файл конфигурации для веб-пакета.

module.exports = {
  entry: [
    'js/jquery.js',
    'js/menu-widget.js',
    'js/menu-widget--fancy-button.js',
    'js/ad-widget.js',
    'js/loading-bar.js',
    'js/loading-bar.fancy.theme.js',
    'js/social.sdk.js',
    'js/analytics.js',
    'js/analytics.seo.js',
    'js/main.js'
  ],
  output: {
    path: './dist',
    filename: 'output.js'
  }
}

Обратите внимание, что весь файл конфигурации — это всего лишь один большой объект, определяющий несколько свойств: entry — массив файлов, которые мы хотим объединить, и output — определяющие path и filename нашего вывода.

Запуск webpack сейчас приведет к тому, что он автоматически прочитает наш конфигурационный файл.

webpack

И генерирует вывод по пути dist с именем файла output.js, как написано в нашем файле конфигурации. Теперь мы можем обслуживать этот js-файл и видеть, что наши теги script резко сокращаются в количестве.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link href="css/main.css" rel="stylesheet" type="text/css">
  <title>Sample</title>
</head>
<body>
  <div><!-- One long DOM --></div>
  <script src="dist/output.js"></script>
</body>
</html>

Как вы можете видеть, веб-пакет на самом деле очень прост — передает ему кучу файлов, он их обрабатывает (массив в этом случае приводит к конкатенации) и выводит нужный файл.

Конкатенация приводит к гораздо меньшему количеству сетевых запросов, а также сокращает наш HTML-файл.

К сожалению, это решает только первую проблему, которую я представил выше:

  1. Много JS-файлов в тегах script означает много сетевых запросов. Это приводит к замедлению времени загрузки (но будет решено HTTP/2).
  2. Есть неявные зависимости. Хотя menu-widget--fancy-button загружается так же, как и любой другой скрипт, на самом деле он зависит от menu-widget, который, в свою очередь, зависит от jquery. Насколько нам известно, это также зависит от loading-bar, но в том-то и дело — мы не знаем, пока не посмотрим на код/документацию.
  3. В связи с вышеизложенным существует неявный порядок загрузки. main.js нельзя размещать сверху, так как он будет выполняться раньше других скриптов, на которые он опирается.
  4. Все глобально (скорее всего)

Это связано с тем, что конкатенация на самом деле просто устраняет симптом, а не корень реальной проблемы Интернета — отсутствие хорошего разрешения зависимостей.

<script src="js/jquery.js"></script>
<script src="js/menu-widget.js"></script>
<script src="js/menu-widget--fancy-button.js"></script>
<script src="js/ad-widget.js"></script>
<script src="js/loading-bar.js"></script>
<script src="js/loading-bar.fancy.theme.js"></script>
<script src="js/social.sdk.js"></script>
<script src="js/analytics.js"></script>
<script src="js/analytics.seo.js"></script>
<script src="js/main.js"></script>

Это все javascript, требуемые страницей.

Тем не менее, main.js — это наша единственная зависимость верхнего уровня, остальные — это библиотеки!

Что, если нам нужно только импортировать наш основной js-файл и позволить ему каким-то образом импортировать свои собственные зависимости?

Это не новая идея. Почти в каждом языке — python, ruby, c, c++, java и т. д. — есть какой-то способ сделать это, будь то через import, include и т. д.

Webpack великолепен, потому что позволяет делать то же самое в javascript, используя синтаксис require или import (в ES6). Это не совсем то, что предоставляет вам этот набор функций (это делают загрузчики модулей), но это то, что читает ваши файлы и генерирует пакет, который вы можете использовать.

В общем, представьте что-то вроде этого:

var string = 'Hello!'
alert(string)

Теперь представьте, что наша строка «Hello!» действительно длинная, и было бы разумно, если бы они находились в разных файлах. Обычно вы делаете что-то вроде этого:

window.string = 'asuperreallylongstring'

сохраняя его в файл, скажем string.js, а файл main.js выглядит так:

alert(window.string)

Затем мы добавляем оба в наш html

<script src="js/string.js"></script>
<script src="js/main.js"></script>

Хотя этот пример немного прост, код javascript, разделенный на несколько файлов, не является чем-то необычным.

Загрузчики модулей позволяют вам, сюрприз, загружать модули. Использование загрузчиков модулей изменяет приведенный выше код на что-то похожее на это:

string.js :

module.exports = 'asuperreallylongstring'

main.js :

var string = require('./string.js')
alert(string)

Указание Webpack на main.js обработает его, увидит, что ему что-то нужно, и объединит файлы вместе. Если мы посмотрим на наш список выше, вы увидите, что загрузка модуля решает все наши проблемы:

  1. Много JS-файлов в тегах script означает много сетевых запросов. Это приводит к замедлению загрузки (но проблема будет решена с помощью HTTP/2) — с помощью сборщика модулей, такого как webpack, мы можем объединить наши модули в один
  2. Есть неявные зависимости. Хотя menu-widget--fancy-button загружается так же, как и любой другой скрипт, на самом деле он зависит от menu-widget, который, в свою очередь, зависит от jquery. Насколько нам известно, это также зависит от loading-bar, но в том-то и дело, что мы на самом деле не знаем, пока не посмотрим на код/документацию. Каждая зависимость явно выражена через require
  3. В связи с вышеизложенным существует неявный порядок загрузки. main.js нельзя размещать сверху, так как он будет выполняться раньше других скриптов, на которые он опирается. Поскольку мы загружаем зависимости по мере необходимости, порядок загрузки теперь является явным
  4. Все глобально (скорее всего) — хотя это все еще возможно, теперь это намного сложнее, и меньше причин для того, чтобы код был глобальным (в отличие от нашего кода выше, в котором требовалось глобальное окно для передачи это данные

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

Итак, как нам скомпилировать наш main.js выше?

В отличие от нашего первого файла конфигурации выше (где мы объединили наши файлы), мы можем просто написать main.js в нашем свойстве entry — webpack автоматически распознает, что ему требуется ./string.js, и загрузит его в наш пакет.

module.exports = {
  entry: 'js/main.js',
  output: {
    path: './dist',
    filename: 'output.js'
  }
}

Запуск webpack сгенерирует dist/output.js, который при запуске на html-странице выдаст предупреждение «superreallylongstring». Выиграть!

Обратите внимание на синтаксис конфигурации записи:

  1. Мы можем передать путь к файлу, и webpack обработает этот единственный файл.
  2. Мы можем передать массив путей, и webpack обработает и соединит их.

Опять же, я хочу, чтобы вы оценили простоту приведенной выше конфигурации веб-пакета. Он не содержит ничего, кроме свойства entry, подробно описывающего файлы, которые веб-пакет будет просматривать и обрабатывать, и содержит свойство output, которое указывает, где будет выводиться сгенерированный файл веб-пакета.

Погрузчики

Помните наш loading-bar.js выше? Давайте предположим, что это что-то действительно простое — он заменяет каждый объект dom, который имеет класс loading-bar, изображением полосы загрузки.

var $ = require('./js/jquery')
$(function () {
  $('.loading-bar').html('<img src="/assets/loading-bar.png" />')
})

Вам не нужно знать jQuery, чтобы следовать этому руководству — просто предположите, что это простой в использовании селектор DOM. В этом конкретном случае он ничего не делает, а выбирает все элементы div с классом «loading-bar» и заменяет его тегом изображения.

Это довольно стандартный javascript (хотя и короткий)

Обратите внимание, однако, что он предполагает что-то — что у нас есть изображение по пути /assets/loading-bar.png на нашем сервере. Опять же, это довольно стандартная практика в javascript — добавление виджета, для которого требуется изображение/css, также требует, чтобы мы добавили это изображение и css на наш сервер.

Это проблематично — assets/loading-bar.png — это неявная зависимость, и, что еще хуже, это даже не javascript! Мы могли бы убедиться, что все наши файлы javascript добавлены на сервер, и каким-то образом наш код все равно не будет работать.

Поскольку мы можем require файлы javascript, почему бы не сделать то же самое для файлов изображений?

var $ = require('./js/jquery')
var image = require('./assets/loading-bar.png')
$(function () {
  $('.loading-bar').html('<img src="' + image + '" />')
})

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

Запрашивая изображение вместо того, чтобы слепо зависеть от URL-адреса, мы снова превращаем неявную зависимость между loading-bar.js и loading-bar.png в явную зависимость, сводя к минимуму вероятность сбоя нашего кода и автоматически имея возможность объединить два файла вместе.

Но подождите! Как это работает? Нам требуется изображение, а не файл js.

Действительно, если вы попытаетесь использовать веб-пакет на loading-bar.js, произойдет сбой с сообщением об ошибке, подобным следующему:

ERROR in ./assets/loading-bar.png
Module parse failed: /path/assets/loading-bar.png Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected character '' (1:0)

Это потому, что webpack не знает, как загрузить наш png-файл. По умолчанию webpack имеет загрузчик модулей javascript, поэтому он сможет разобрать и понять что-то вроде:

module.exports = 'areallylongstring'

Но он не сможет прочитать png, который больше похож на:

8950 4e47 0d0a 1a0a 0000 000d 4948 4452
0000 02a8 0000 012c 0802 0000 0080 13d6
5800 0000 1974 4558 7453 6f66 7477 6172
6500 4164 6f62 6520 496d 6167 6552 6561
6479 71c9 653c 0000 8a44 4944 4154 78da

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

Итак, давайте продолжим и предоставим веб-пакету возможность загружать pngs.

Давайте сначала подумаем об этом. Что мы можем передать в качестве src нашему тегу img? Data URI — хороший вариант — это схема, которая позволяет нам превратить наш png в строку. Вот пример тега img с png, загруженным как data-uri:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

Превращая png в строку и требуя от него loading-bar.js, мы делаем что-то очень похожее на то, что мы делали ранее, требуя «superreallylongstring» из другого файла — только на этот раз нам требуется очень длинная строка, которая разрешается в png. Обратите внимание: несмотря на то, что нам требуется изображение в javascript, мы по-прежнему используем те же концепции, что и ранее.

В любом случае, давайте продолжим и на самом деле реализуем это с помощью webpack. Сначала добавим загрузчик, который позволяет нам превращать pngs в data-uris — файл url-loader. Установите его, запустив npm install url-loader --save-dev

После установки добавим его в наш файл конфигурации:

module.exports = {
  entry: 'loading-bar.js',
  output: {
    path: './dist/',
    filename: 'output.js'
  },
  module: {
    loaders: [{
      test: /\.png$/,
      loader: 'url-loader'
    }]
  }
}

Обратите внимание, единственное, что мы добавили — конфигурацию для нашего module loaders

Как видите, загрузчики — это массив объектов — это потому, что мы можем расширить webpack набором загрузчиков, которые обрабатывают разные типы файлов.

Свойство внутри нашего объекта загрузчика говорит само за себя. Первый — загрузчик, который содержит имя нашего загрузчика («url-loader»). Следующим является test, который содержит регулярное выражение. Если наш тест регулярного выражения совпадает с именем файла, мы используем загрузчик для этого файла.

Если мы запустим webpack, файл js будет скомпилирован, вводя data-uri изображения в loading-bar.js

Здесь проявляется большая часть возможностей веб-пакета. Он предоставляет полнофункциональную систему управления, которая объединяет ваш код и ресурсы в нечто, что может быть легко предоставлено конечному пользователю. Он делает это, имея возможность «научиться» загружать разные файлы.

Babel де-факто является транспилятором для Javascript, и один из наиболее распространенных вариантов использования webpack — позволить ему транспилировать Javascript ES6 в Javascript ES5 (который может понять большинство браузеров).

Мы можем легко использовать babel, сообщив веб-пакету, что наши js-файлы написаны на es6 и что он должен загрузить их с помощью загрузчика для Babel, метко названного babel-loader.

module.exports = {
  entry: 'loading-bar.js',
  output: {
    path: './dist/',
    filename: 'output.js'
  },
  module: {
    loaders: [{
      test: /\.png$/,
      loader: 'url'
    },{
      test: /\.js$/,
      loader: 'babel-loader'
    }]
  }
}

Обратите внимание, что концепция загрузчиков позволяет веб-пакету полностью позаботиться об управлении активами и разрешении зависимостей. На самом деле это упрощает многие существующие рабочие процессы.

Представьте себе CSS-фреймворк, который может включать не только css, но и собственные шрифты, изображения и js! Раньше это решалось путем загрузки всех ресурсов, проверки того, что все находится в правильном каталоге, обновления каждого из ресурсов при появлении новой версии и т. д.

css
├─ framework.css
└─ framework.min.css
js
├─ framework.js
└─ framework.min.js
fonts
├─ framework-font.ttf
├─ framework-font.svg
└─ framework-font.woff

Используя webpack, фреймворк/библиотека может иметь только одну точку входа, которая объединяет все, что приводит к более простому и прямому способу включения этой зависимости.

require('framework') // automatically takes care of its own assets

Это дает дополнительное преимущество в виде простого управления пакетами — теперь мы можем использовать npm install framework и использовать его в нашем интерфейсе.

Теперь, если мы используем наш framework.css выше, мы должны отметить, что он включает в себя некоторые файлы, которые наш веб-пакет еще не знает, как загружать. А именно, у него нет загрузчика для css и различных файлов шрифтов, поэтому давайте обновим наш файл конфигурации, чтобы позаботиться об этом:

module.exports = {
  entry: 'loading-bar.js',
  output: {
    path: './dist/',
    filename: 'output.js'
  },
  module: {
    loaders: [{
      test: /\.png$/,
      loader: 'url'
    },{
      test: /\.js$/,
      loader: 'babel-loader'
    },{
      test: /\.css$/,
      loader: 'style-loader!css-loader'
    },{
      test: /\.(ttf|svg|woff)$/,
      loader: 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]'
    }]
  }
}

Все та же общая идея, но что это такое! Зачем нужны вопросительные и восклицательные знаки?

Оказывается, загрузчики веб-пакетов компонуемые и расширяемые.

loader: 'style-loader!css-loader'

Восклицательный знак (!) здесь позволяет загрузчикам применяться один за другим (как оператор канала в Linux), справа налево. По сути, эта конкретная строка сообщает веб-пакету load matching files as css, а затем load them as a style.

Это кажется любопытным. Почему мы загружаем файлы css как «css», а не как «стиль»? Это потому, что эти два загрузчика делают разные вещи. css loader загружает файл css во что-то, что может понять javascript, а style loader загружает его как фактический стиль, внедряя css в DOM с тегом style. С помощью конвейера, как мы видим здесь, мы разрешаем использование CSS на нашей странице.

loader: 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]'

Строка для загрузчика файлов кажется немного более сложной, а сам загрузчик на самом деле довольно интересен. Знак вопроса (?) означает, что мы собираемся передать загрузчику некоторые параметры, определенные с использованием синтаксиса key=value и разделенные символом (&). По сути, они аналогичны синтаксису HTTP GET URL.

Итак, если посмотреть на это глубже, кажется, что у нас есть File Loader, в котором sha512 соответствует hash, digest соответствует hex, а name соответствует [hash].[ext]. Этот синтаксис стал намного чище в webpack 2, который передает параметры загрузчика как фактический объект.

{
  loader: 'file-loader',
  options: {
    hash: 'sha512',
    digest: 'hex',
    name: '[hash].[ext]'
  }
}

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

Как вы можете себе представить, включение активов в качестве URI DATA в наш код javascript может быть не лучшей идеей. Конечно, это работает с некоторыми небольшими активами (например, с образцом красной точки, который я использовал выше), но для больших активов было бы лучше использовать их как разные независимые файлы. Они заботятся о двух вещах — уменьшают полезную нагрузку javascript и позволяют браузеру независимо кэшировать активы. Тем не менее, было бы здорово по-прежнему использовать преимущества веб-пакета.

Вот тут-то и появляется File Loader — он позволяет вам обслуживать необходимые файлы как разные активы. Когда загрузчик файлов используется для require файла, он возвращает URL-адрес, который разрешается для этого конкретного файла

Таким образом, если мы использовали загрузчик файлов для загрузки png в нашем примере loading-bar.js выше, вместо требуемого файла, создающего URI DATA, он выдает общедоступный URL-адрес для этого img, который мы используем для браузера для получения самого актива.

Если загрузчик файлов возвращает URL-адрес, само собой разумеется, что файл, на который он ссылается, должен быть каким-то образом доступен через Интернет. Однако веб-пакет — это только наш компилятор, а не сервер, поэтому мы несем ответственность за их обслуживание. К счастью, webpack упрощает это, создавая файлы, которые нам нужно обслуживать — они помещаются в путь вывода, который мы определили.

output: {
  path: './dist/',
  filename: 'output.js'
}

Итак, в нашем примере выше, если фреймворку требуется framework.ttf, webpack скопирует файл в наш каталог dist, который мы можем легко обслуживать!

Параметры, которые мы передаем загрузчику файлов, имеют смысл, если принять это во внимание — name — это имя файла после того, как мы скопируем его в dist, а строка '[hash].[ext]' для имени означает, что имя файла — это хеш, за которым следует точка, за которой следует расширение файла, а наша хеш-функция — sha512. Пример имени файла, например, может быть 1be2c22c29a9235cdccd7df68d5a4e4b.ttf.

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

Поскольку файлы копируются в выходной путь, указанный вами в файле конфигурации, вам нужно будет поместить эти файлы на свой сервер и обслуживать их. Поскольку они являются активами, они, вероятно, будут находиться в подкаталоге, таком как http://yoursite.tld/assets/. Если мы используем эту настройку, нам нужно будет указать веб-пакету добавлять «активы /» к URL-адресам, которые он создает. Webpack разрешает это с помощью параметра «publicPath» на output.

output: {
  path: './dist/',
  publicPath: '/assets/'
  filename: 'output.js'
}

С учетом вышеизложенного требуемый файл теперь будет возвращать что-то похожее на /assets/1be2c22c29a9235cdccd7df68d5a4e4b.ttf

Обратите внимание, насколько эта система расширяема — если нам когда-нибудь понадобится обслуживать наши активы через cdn, мы можем просто изменить наш общедоступный путь на URL-адрес нашего cdn.

output: {
  path: './dist/',
  publicPath: 'https://mycdn.com/cdnkey/'
  filename: 'output.js'
}

И URL теперь будет https://mycdn.com/cdnkey/1be2c22c29a9235cdccd7df68d5a4e4b.ttf

К этому моменту вы, надеюсь, сможете увидеть, что мощные загрузчики позволяют нам — мы можем использовать их, чтобы научить «webpack» обрабатывать файлы по-разному в зависимости от критериев. Это упрощает поддержку практически любого типа файлов — пока для него есть загрузчик, webpack может его загрузить.

  • Нужно использовать sass? Для этого есть загрузчик: sass-loader
  • Нужно использовать json, xml или toml? Для этого есть загрузчик: json-loader, xml-loader и toml-loader
  • Хотите использовать шаблоны? Есть rails-erb-loader, haml-loader, jade-html-loader и т.д.
  • Есть загрузчик для всего, что только можно придумать!

Природа «загрузчиков» также позволяет создавать пользовательские оболочки или функциональные возможности для существующего кода — мы впервые увидели это с помощью style loader, который загружает то, что передается ему в виде блоков стиля DOM. Другим примером функциональности «обертывания» загрузчика является bundle-loader, который делает ленивую загрузку пакета, также известную как отложенная загрузка или разделение кода, невероятно простой.

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

Заворачивать

Ого, это довольно долго читать! Надеюсь, теперь у вас есть более полное представление о том, как работает веб-пакет (и объединение модулей в целом), и теперь вы можете видеть, как каждая часть конфигурации веб-пакета подходит.

Webpack — очень расширяемый и мощный инструмент, и огромное количество функций, которые он может выполнять, означает, что существующие файлы конфигурации могут быть довольно длинными и сложными. Поняв, как это работает, вы теперь сможете легче понять их, а также расширять и даже создавать свои собственные конфигурации веб-пакетов.

Есть еще несколько тем, которые мы можем обсудить, такие как плагины Webpack, сервер разработки, лучшие практики (конфигурации разработки и производства), которые я мог бы вернуться к другому учебнику.

Дальнейшее чтение

Документы по конфигурации Webpack 2

Вебпак как сделать

Примеры веб-пакетов