Может кто-нибудь объяснить Webpack CommonsChunkPlugin

Я получаю общий смысл, что CommonsChunkPlugin просматривает все точки входа, проверяет, есть ли между ними общие пакеты/зависимости и разделяет их на свой собственный пакет.

Итак, допустим, у меня есть следующая конфигурация:

...
enrty : {
    entry1 : 'entry1.js', //which has 'jquery' as a dependency
    entry2 : 'entry2.js', //which has 'jquery as a dependency
    vendors : [
        'jquery',
        'some_jquery_plugin' //which has 'jquery' as a dependency
    ]
},
output: {
    path: PATHS.build,
    filename: '[name].bundle.js'
}
...

Если я свяжусь без использования CommonsChunkPlugin

В итоге у меня появятся 3 новых файла пакета:

  • entry1.bundle.js, который содержит полный код из entry1.js и jquery и содержит собственную среду выполнения
  • entry2.bundle.js, который содержит полный код из entry2.js и jquery и содержит собственную среду выполнения
  • vendors.bundle.js, который содержит полный код из jquery и some_jquery_plugin и содержит свое собственное время выполнения

Это, очевидно, плохо, потому что я потенциально буду загружать jquery 3 раза на страницу, поэтому мы этого не хотим.

Если я свяжусь с помощью CommonsChunkPlugin

В зависимости от того, какие аргументы передаются на CommonsChunkPlugin, произойдет следующее:

  • CASE 1: Если я пройду { name : 'commons' }, у меня появятся следующие файлы пакетов:

    • entry1.bundle.js, который содержит полный код из entry1.js, требование для jquery и не содержит время выполнения
    • entry2.bundle.js, который содержит полный код из entry2.js, требование для jquery и не содержит время выполнения
    • vendors.bundle.js, который содержит полный код из some_jquery_plugin, требование для jquery и не содержит время выполнения
    • commons.bundle.js, который содержит полный код из jquery и содержит время выполнения

    Таким образом, мы получим несколько небольших пакетов в целом, а время выполнения содержится в пакете commons. Довольно нормально, но не идеально.

  • CASE 2: Если я пройду { name : 'vendors' }, у меня появятся следующие файлы пакетов:

    • entry1.bundle.js, который содержит полный код из entry1.js, требование для jquery и не содержит время выполнения
    • entry2.bundle.js, который содержит полный код из entry2.js, требование для jquery и не содержит время выполнения
    • vendors.bundle.js, который содержит полный код из jquery и some_jquery_plugin и содержит время выполнения.

    Таким образом, мы снова получаем несколько небольших пакетов, но среда выполнения теперь содержится в пакете vendors. Это немного хуже, чем в предыдущем случае, поскольку среда выполнения теперь находится в пакете vendors.

  • CASE 3: Если я пройду { names : ['vendors', 'manifest'] }, у меня появятся следующие файлы пакетов:

    • entry1.bundle.js, который содержит полный код из entry1.js, требование для jquery и не содержит время выполнения
    • entry2.bundle.js, который содержит полный код из entry2.js, требование для jquery и не содержит время выполнения
    • vendors.bundle.js, который содержит полный код из jquery и some_jquery_plugin и не содержит среды выполнения
    • manifest.bundle.js, который содержит требования для каждого другого пакета и содержит время выполнения

    Таким образом, мы заканчиваем небольшими пакетами в целом, а время выполнения содержится в пакете manifest. Это идеальный случай.

Что я не понимаю/Я не уверен, что понимаю

  • В CASE 2 почему мы закончили с пакетом vendors, содержащим как общий код (jquery), так и все, что осталось от записи vendors (some_jquery_plugin)? По моему мнению, что CommonsChunkPlugin здесь заключалось в том, что он собрал общий код (jquery), и поскольку мы вынудили его вывести его в пакет vendors, он вроде как "объединил" общий код в vendors bundle (который теперь содержит только код из some_jquery_plugin). Пожалуйста, подтвердите или объясните.

  • В CASE 3 Я не понимаю, что произошло, когда мы передали { names : ['vendors', 'manifest'] } плагину. Почему/как пакет vendors сохранялся неповрежденным, содержащим как jquery, так и some_jquery_plugin, когда jquery явно является общей зависимостью, и почему был создан сгенерированный файл manifest.bundle.js так, как он был создан (требующий всех другие пакеты и содержащие время выполнения)?

Ответ 1

Вот как работает CommonsChunkPlugin.

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

CommonsChunkPlugin выполняется во время фазы оптимизации Webpack, что означает, что он работает в памяти, незадолго до того, как куски запечатаны и записаны на диск.

Когда определено несколько общих кусков, они обрабатываются по порядку. В вашем случае 3 это похоже на запуск плагина дважды. Но учтите, что CommonsChunkPlugin может иметь более сложную конфигурацию (minSize, minChunks и т.д.), Которая влияет на перемещение модулей.

CASE 1:

  • Есть 3 entry куска (entry1, entry2 и vendors).
  • Конфигурация устанавливает блок commons как общий фрагмент.
  • Плагин обрабатывает общий фрагмент commons (так как кусок не существует, он создается):
    • Он собирает модули, которые используются более одного раза в других фрагментах: entry1, entry2 и vendors используют jquery, поэтому модуль удаляется из этих фрагментов и добавляется в блок commons.
    • Блок commons помечен как фрагмент entry, в то время как фрагменты entry1, entry2 и vendors не отмечены как entry.
  • Наконец, поскольку блок commons - это блок entry, он содержит модуль времени выполнения и jquery.

CASE 2:

  • Есть 3 entry куска (entry1, entry2 и vendors).
  • Конфигурация устанавливает блок vendors как общий фрагмент.
  • Плагин обрабатывает общий кусок vendors:
    • Он собирает модули, которые используются более одного раза в других фрагментах: entry1 и entry2 используют jquery, поэтому модуль удаляется из этих фрагментов (обратите внимание, что он не добавлен в блок vendors потому что кусок vendors уже содержит его).
    • Блок vendors помечен как фрагмент entry, в то время как фрагменты entry1 и entry2 не отмечены как entry.
  • Наконец, поскольку блок vendors является блоком entry, он содержит модули времени выполнения и jquery/jquery_plugin.

CASE 3:

  • Есть 3 entry куска (entry1, entry2 и vendors).
  • Конфигурация устанавливает кусок vendors и фрагмент manifest как обычные куски.
  • Плагин создает кусок manifest, поскольку он не существует.
  • Плагин обрабатывает общий кусок vendors:
    • Он собирает модули, которые используются более одного раза в других фрагментах: entry1 и entry2 используют jquery, поэтому модуль удаляется из этих фрагментов (обратите внимание, что он не добавлен в блок vendors потому что кусок vendors уже содержит его).
    • Блок vendors помечен как фрагмент entry, в то время как фрагменты entry1 и entry2 не отмечены как entry.
  • Плагин обрабатывает общий кусок manifest (так как кусок не существует, он создается):
    • Он собирает модули, которые используются более одного раза в других кусках: поскольку нет модулей, используемых более одного раза, модуль не перемещается.
    • Блок manifest помечен как entry chunk, а entry1, entry2 и vendors не отмечены как entry.
  • Наконец, поскольку кусок manifest представляет собой фрагмент entry, он содержит среду выполнения.

Надеюсь, что это поможет.