Хтось може пояснити веб-пакет CommonsChunkPlugin


82

Я розумію загальну суть того, що 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і містить власний час виконання

Це, очевидно, погано, тому що я потенційно завантажуватиму jquery3 рази на сторінці, тому ми цього не хочемо.

Якщо я зв’язую з використанням CommonsChunkPlugin

Залежно від того, які аргументи я передаю CommonsChunkPluginбудь-якому з наступного:

  • ВИПАДОК 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комплекті. Дуже добре, але не ідеально.

  • СЛУЧАЙ 2: Якщо я пройду, { name : 'vendors' }я отримаю наступні файли набору:

    • entry1.bundle.jsякий містить повний код з entry1.js, вимога jqueryта не містить час виконання
    • entry2.bundle.jsякий містить повний код з entry2.js, вимога jqueryта не містить час виконання
    • vendors.bundle.jsякий містить повний код з jqueryта some_jquery_pluginі містить час виконання.

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

  • СЛУЧАЙ 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пакет (який тепер містив лише код з some_jquery_plugin). Будь ласка, підтвердьте або поясніть.

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


Для випадку 1, я думаю, вам слід вказати властивість minChunks.
Марко

10
Я так багато дізнався з вашого запитання , дякую!
Рафаель Айнг,

1
Щиро дякую за те, що ви запитували це і вичищали мої сумніви весь цей час щодо цього плагіна ❤
Гленн Мохаммад,

Може хтось знає, як виглядатимуть ці приклади у Webpack 4?
StalkAlex

Відповіді:


105

Ось як це CommonsChunkPluginпрацює.

Загальний шматок "отримує" модулі, спільні для кількох вхідних шматків. Хороший приклад складної конфігурації можна знайти у сховищі Webpack .

CommonsChunkPluginЗапускається на етапі оптимізації Webpack, що означає , що вона працює в пам'яті, як раз перед скибки запечатані і записані на диск.

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

СПРАВА 1:

  1. Є 3 entryшматки ( entry1, entry2і vendors).
  2. Конфігурація встановлює commonsшматок як загальний шматок.
  3. Плагін обробляє commonsзагальний шматок (оскільки шматок не існує, він створюється):
    1. Він збирає модулі, які використовуються більш ніж один раз в інших кусках: entry1, entry2і vendorsвикористовувати jqueryтаким чином , модуль видаляється з цих шматків і додається в commonsблок.
    2. commonsШматок позначений як entryшматок в той час як entry1, entry2і vendorsшматки , як unflagged entry.
  4. Нарешті, оскільки commonsфрагмент - це entryфрагмент, він містить час виконання та jqueryмодуль.

СПРАВА 2:

  1. Є 3 entryшматки ( entry1, entry2і vendors).
  2. Конфігурація встановлює vendorsшматок як загальний шматок.
  3. Плагін обробляє vendorsзагальний шматок:
    1. Він збирає модулі, які використовуються більше одного разу в інших фрагментах: entry1і entry2використовуйте, jqueryщоб модуль був видалений з цих фрагментів (зауважте, що він не додається до vendorsфрагмента, оскільки цей vendorsфрагмент вже його містить).
    2. vendorsШматок позначений як entryшматок в той час як entry1і entry2шматки , як unflagged entry.
  4. Нарешті, оскільки vendorsфрагмент є entryфрагментом, він містить час виконання та jquery/ jquery_pluginмодулі.

СПРАВА 3:

  1. Є 3 entryшматки ( entry1, entry2і vendors).
  2. Конфігурація встановлює vendorsшматок і manifestшматок як загальні шматки.
  3. Плагін створює manifestшматок, оскільки його не існує.
  4. Плагін обробляє vendorsзагальний шматок:
    1. Він збирає модулі, які використовуються більше одного разу в інших фрагментах: entry1і entry2використовуйте, jqueryщоб модуль був видалений з цих фрагментів (зауважте, що він не додається до vendorsфрагмента, оскільки цей vendorsфрагмент вже його містить).
    2. vendorsШматок позначений як entryшматок в той час як entry1і entry2шматки , як unflagged entry.
  5. Плагін обробляє manifestзагальний шматок (оскільки шматок не існує, він створюється):
    1. Він збирає модулі, які використовуються більше одного разу в інших фрагментах: оскільки немає модулів, що використовуються більше одного разу, жоден модуль не переміщується.
    2. manifestШматок позначений як entryшматок в той час entry1, entry2і vendorsє unflagged , як entry.
  6. Нарешті, оскільки manifestшматок - це entryшматок, він містить час виконання.

Сподіваюся, це допоможе.


Кілька речей, які я хочу запитати / пояснити, будь-ласка, додайте до вашої відповіді також ці пункти: 1) Чи можете ви зробити те саме поетапне пояснення для СПРАВИ 1, щоб відповідь була повна на 1000%? 2) Запуск плагіна за допомогою { names : ['vendors', 'manifest'] }схожий на запуск його двічі, один раз разом { name : 'vendors' }і один раз { name : 'manifest' }, правильно? 3) Коли ми говоримо "Плагін обробляє загальний шматок", ми маємо на увазі, що він створює вміст, який буде виплювати у bundle.jsфайл, в пам'ять, правильно? 4) Поки він не "обробив усі загальні фрагменти", він взагалі не записав жодного виходу у файл, це все в пам'яті
Dimitris Karagiannis

2
У мене ще одне запитання, якщо вам хочеться відповісти. Скажімо, що в моєму прикладі зверху entry1.jsі entry2.jsміж ними був інший спільний файл, крім jqueryфайлу, назвемо його ownLib.js. У ВИПАДКАХ 2 та ВИПАДКУ 3, ownLib.jsчи потрапили б vendors.bundle.jsправильно? Як би ви зробили так, щоб загальні файли, крім файлів постачальників, були розділені на їх власний шматок, крім vendorsшматка? Вибачте, що заважаю, але я все ще вчусь користуватися веб-пакетом
Dimitris Karagiannis

7
Так, це правильно: ownLib.jsбуло б поміщено в перший загальний шматок. Якщо ви хочете , щоб зібрати загальні залежності в іншому chunck, ви повинні пройти що - щось на зразок цього: { names : ['common', 'vendors', 'manifest'] }.
Laurent Etiemble

6
Чудове питання, чудова відповідь, чудова дискусія. Здається, я зрозумів це нарешті.
oluckyman

3
Я провів останній день, читаючи документи CommonsChunkPlugin, і це перше місце, яке я прочитав, що після виконання оброблені фрагменти "не позначені як запис". Це в основному пояснює все, з чим я мав проблеми - якщо б я міг проголосувати більше одного разу, я б.
Coderer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.