web-dev-qa-db-fra.com

Quelqu'un peut-il expliquer le protocole CommonsChunkPlugin de Webpack?

Je comprends que le CommonsChunkPlugin examine tous les points d’entrée, vérifie s’il existe des paquets/dépendances communs entre eux et les sépare dans leur propre paquet.

Supposons donc que j'ai la configuration suivante:

...
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'
}
...

Si je bundle sans utiliser CommonsChunkPlugin

Je vais me retrouver avec 3 nouveaux fichiers bundle:

  • entry1.bundle.js qui contient le code complet de entry1.js et jquery et contient son propre runtime
  • entry2.bundle.js qui contient le code complet de entry2.js et jquery et contient son propre runtime
  • vendors.bundle.js qui contient le code complet de jquery et some_jquery_plugin et contient son propre runtime

C'est évidemment mauvais parce que je vais potentiellement charger jquery 3 fois dans la page, donc nous ne voulons pas de cela.

Si je bundle en utilisant CommonsChunkPlugin

En fonction des arguments que je transmets à CommonsChunkPlugin, l'un des événements suivants se produira:

  • CAS 1: Si je réussis { name : 'commons' } Je vais me retrouver avec les fichiers suivants:

    • entry1.bundle.js qui contient le code complet de entry1.js, une exigence pour jquery et ne contient pas le runtime
    • entry2.bundle.js qui contient le code complet de entry2.js, une exigence pour jquery et ne contient pas le runtime
    • vendors.bundle.js qui contient le code complet de some_jquery_plugin, une exigence pour jquery et ne contient pas le runtime
    • commons.bundle.js qui contient le code complet de jquery et contient le runtime

    De cette façon, nous nous retrouvons avec des paquets plus petits dans l’ensemble et le temps d’exécution est contenu dans le paquet commons. Assez correct mais pas idéal.

  • CAS 2: Si je réussis { name : 'vendors' } Je vais me retrouver avec les fichiers suivants:

    • entry1.bundle.js qui contient le code complet de entry1.js, une exigence pour jquery et ne contient pas le runtime
    • entry2.bundle.js qui contient le code complet de entry2.js, une exigence pour jquery et ne contient pas le runtime
    • vendors.bundle.js qui contient le code complet de jquery et some_jquery_plugin et contient le temps d'exécution.

    De cette façon, encore une fois, nous nous retrouvons avec des bundles plus petits mais le runtime est maintenant contenu dans le bundle vendors. C'est un peu pire que le cas précédent, car l'exécution est maintenant dans le bundle vendors.

  • CAS 3: Si je réussis { names : ['vendors', 'manifest'] } Je vais me retrouver avec les fichiers suivants:

    • entry1.bundle.js qui contient le code complet de entry1.js, une exigence pour jquery et ne contient pas le runtime
    • entry2.bundle.js qui contient le code complet de entry2.js, une exigence pour jquery et ne contient pas le runtime
    • vendors.bundle.js qui contient le code complet de jquery et some_jquery_plugin et ne contient pas le runtime
    • manifest.bundle.js qui contient les conditions requises pour tous les autres ensembles et contient le runtime

    De cette façon, nous nous retrouvons avec des paquets plus petits dans l’ensemble et le temps d’exécution est contenu dans le paquet manifest. C'est le cas idéal.

Ce que je ne comprends pas/je ne suis pas sûr de comprendre

  • Dans CASE 2 pourquoi nous nous sommes retrouvés avec le paquet vendors contenant à la fois le code commun (jquery) et tout ce qui restait de l’entrée vendors ( some_jquery_plugin)? D'après ce que j'ai compris, la CommonsChunkPlugin ici a rassemblé le code commun (jquery) et, depuis que nous l'avons forcée à l'afficher dans le bundle vendors, de "fusionner" le code commun dans le bundle vendors (qui ne contenait plus que le code de some_jquery_plugin). Veuillez confirmer ou expliquer.

  • Dans CAS Je ne comprends pas ce qui s’est passé quand on est passé { names : ['vendors', 'manifest'] } au plugin. Pourquoi/comment le paquet vendors a-t-il été conservé intact, contenant à la fois jquery et some_jquery_plugin, quand jquery est clairement une dépendance courante et pourquoi le manifest.bundle.js fichier créé de la manière dont il a été créé (nécessitant tous les autres bundles et contenant le moteur d’exécution)?

79

Voici comment fonctionne CommonsChunkPlugin.

Un bloc commun "reçoit" les modules partagés par plusieurs blocs d'entrée. Vous trouverez un bon exemple de configuration complexe dans référentiel Webpack .

Le CommonsChunkPlugin est exécuté pendant la phase d'optimisation de Webpack, ce qui signifie qu'il fonctionne en mémoire, juste avant que les morceaux ne soient scellés et écrits sur le disque.

Lorsque plusieurs morceaux courants sont définis, ils sont traités dans l’ordre. Dans votre cas 3, c'est comme si vous exécutiez le plugin deux fois. Mais notez que CommonsChunkPlugin peut avoir une configuration plus complexe (minSize, minChunks, etc.) qui a un impact sur la façon dont les modules sont déplacés.

CAS 1:

  1. Il y a 3 entry morceaux (entry1, entry2 et vendors).
  2. La configuration définit le fragment commons comme un fragment commun.
  3. Le plugin traite le morceau commun commons (car le morceau n'existe pas, il est créé):
    1. Il rassemble les modules utilisés plus d'une fois dans les autres morceaux: entry1, entry2 et vendors utilisent jquery afin que le module soit supprimé de ces fragments et qu’il soit ajouté au fragment commons.
    2. Le morceau commons est marqué comme un morceau entry alors que le entry1, entry2 et vendors, les fragments sont sans drapeau sous le nom de entry.
  4. Enfin, puisque le morceau commons est un morceau entry, il contient le runtime et le module jquery.

CAS 2:

  1. Il y a 3 entry morceaux (entry1, entry2 et vendors).
  2. La configuration définit le fragment vendors comme un fragment commun.
  3. Le plugin traite le fragment vendors commun:
    1. Il rassemble les modules utilisés plus d'une fois dans les autres morceaux: entry1 et entry2 utilise jquery pour que le module soit supprimé de ces morceaux (notez qu'il n'est pas ajouté au morceau vendors, car le paquet vendors le contient déjà).
    2. Le morceau vendors est marqué comme un morceau entry alors que le entry1 et entry2 _ Les morceaux ne portent pas le symbole entry.
  4. Enfin, puisque le morceau vendors est un morceau entry, il contient le runtime et le jquery/jquery_plugin modules.

CAS 3:

  1. Il y a 3 entry morceaux (entry1, entry2 et vendors).
  2. La configuration définit les fragments vendors et manifest comme des fragments courants.
  3. Le plugin crée le morceau manifest car il n’existe pas.
  4. Le plugin traite le fragment vendors commun:
    1. Il rassemble les modules utilisés plus d'une fois dans les autres morceaux: entry1 et entry2 utilise jquery pour que le module soit supprimé de ces morceaux (notez qu'il n'est pas ajouté au morceau vendors, car le paquet vendors le contient déjà).
    2. Le morceau vendors est marqué comme un morceau entry alors que le entry1 et entry2 _ Les morceaux ne portent pas le symbole entry.
  5. Le plugin traite le morceau commun manifest (car le morceau n'existe pas, il est créé):
    1. Il regroupe les modules utilisés plus d'une fois dans les autres blocs: aucun module n'étant utilisé plus d'une fois, aucun module n'est déplacé.
    2. Le morceau manifest est marqué comme étant entry alors que le entry1, entry2 et vendors sont sans drapeau comme entry.
  6. Enfin, puisque le morceau manifest est un morceau entry, il contient le runtime.

J'espère que ça aide.

103
Laurent Etiemble