javascript - splitchunks - ¿Alguien puede explicar el CommonsChunkPlugin de Webpack?
webpack vendor chunk (1)
Tengo la
CommonsChunkPlugin
general de que
CommonsChunkPlugin
examina todos los puntos de entrada, comprueba si hay paquetes / dependencias comunes entre ellos y los separa en su propio paquete.
Entonces, supongamos que tengo la siguiente configuración:
...
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 hago un paquete sin usar
CommonsChunkPlugin
Terminaré con 3 nuevos paquetes de archivos:
-
entry1.bundle.jsque contiene el código completo deentry1.jsyjqueryy contiene su propio tiempo de ejecución -
entry2.bundle.jsque contiene el código completo deentry2.jsyjqueryy contiene su propio tiempo de ejecución -
vendors.bundle.jsque contiene el código completo dejqueryysome_jquery_pluginy contiene su propio tiempo de ejecución
Esto obviamente es malo porque potencialmente
jquery
3 veces en la página, por lo que no queremos eso.
Si hago un paquete usando
CommonsChunkPlugin
Dependiendo de los argumentos que le pase a
CommonsChunkPlugin
cualquiera de los siguientes:
-
CASO 1: si paso
{ name : ''commons'' }terminaré con los siguientes archivos de paquete:-
entry1.bundle.jsque contiene el código completo deentry1.js, un requisito parajqueryy no contiene el tiempo de ejecución -
entry2.bundle.jsque contiene el código completo deentry2.js, un requisito parajqueryy no contiene el tiempo de ejecución -
vendors.bundle.jsque contiene el código completo desome_jquery_plugin, un requisito parajqueryy no contiene el tiempo de ejecución -
commons.bundle.jsque contiene el código completo dejqueryy contiene el tiempo de ejecución
De esta manera, terminamos con algunos paquetes más pequeños en general y el tiempo de ejecución está contenido en el paquete
commons. Bastante bien pero no ideal. -
-
CASO 2: Si paso
{ name : ''vendors'' }terminaré con los siguientes archivos de paquete:-
entry1.bundle.jsque contiene el código completo deentry1.js, un requisito parajqueryy no contiene el tiempo de ejecución -
entry2.bundle.jsque contiene el código completo deentry2.js, un requisito parajqueryy no contiene el tiempo de ejecución -
vendors.bundle.jsque contiene el código completo dejqueryysome_jquery_pluginy contiene el tiempo de ejecución.
De esta manera, nuevamente, terminamos con algunos paquetes más pequeños en general, pero el tiempo de ejecución ahora está contenido en el paquete de
vendors. Es un poco peor que el caso anterior, ya que el tiempo de ejecución ahora está en el paquete devendors. -
-
CASO 3: si paso
{ names : [''vendors'', ''manifest''] }terminaré con los siguientes archivos de paquete:-
entry1.bundle.jsque contiene el código completo deentry1.js, un requisito parajqueryy no contiene el tiempo de ejecución -
entry2.bundle.jsque contiene el código completo deentry2.js, un requisito parajqueryy no contiene el tiempo de ejecución -
vendors.bundle.jsque contiene el código completo dejqueryysome_jquery_pluginy no contiene el tiempo de ejecución -
manifest.bundle.jsque contiene requisitos para cada otro paquete y contiene el tiempo de ejecución
De esta manera, terminamos con algunos paquetes más pequeños en general y el tiempo de ejecución está contenido en el paquete
manifest. Este es el caso ideal. -
Lo que no entiendo / No estoy seguro de entender
-
En el CASO 2, ¿por qué terminamos con el paquete de
vendorscontiene tanto el código común (jquery) como lo que quedó de la entrada devendors(some_jquery_plugin)? Según tengo entendido, lo que hizoCommonsChunkPluginaquí fue que recopiló el código común (jquery), y como loCommonsChunkPluginal paquete devendors, de alguna manera "fusionó" el código común en el paquete devendors(que ahora solo contenía el código desome_jquery_plugin). Por favor confirme o explique. -
En el CASO 3 , no entiendo lo que sucedió cuando pasamos
{ names : [''vendors'', ''manifest''] }al complemento. Por qué / cómo se mantuvo intacto el paquete devendors, que contenía tantojquerycomosome_jquery_plugin, cuandojqueryes claramente una dependencia común, y por qué el archivomanifest.bundle.jsgenerado se creó de la manera en que se creó (requiriendo todos los demás paquetes y conteniendo el tiempo de ejecución )?
Así es como funciona el
CommonsChunkPlugin
.
Un fragmento común "recibe" los módulos compartidos por varios fragmentos de entrada. Un buen ejemplo de una configuración compleja se puede encontrar en el repositorio de Webpack .
CommonsChunkPlugin
se ejecuta durante la fase de optimización de Webpack, lo que significa que funciona en la memoria, justo antes de que los fragmentos se sellen y escriban en el disco.
Cuando se definen varios fragmentos comunes, se procesan en orden.
En su caso 3, es como ejecutar el complemento dos veces.
Pero tenga en cuenta que
CommonsChunkPlugin
puede tener una configuración más compleja (minSize, minChunks, etc.) que afecta la forma en que se mueven los módulos.
CASO 1:
-
Hay 3 fragmentos de
entry(entry1,entry2yvendors). -
La configuración establece el fragmento de
commonscomo un fragmento común. -
El complemento procesa el fragmento común común (dado que el fragmento no existe, se crea):
-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
entry1,entry2y losvendorsusanjquerypor lo que el módulo se elimina de estos fragmentos y se agrega al fragmentocommons. -
El fragmento de
commonsse marca como un fragmento deentrymientras que los fragmentos deentry1,entry2yvendorsestán sin marcar comoentry.
-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
-
Finalmente, dado que el fragmento
commonses un fragmento deentry, contiene el tiempo de ejecución y el módulojquery.
CASO 2:
-
Hay 3 fragmentos de
entry(entry1,entry2yvendors). -
La configuración establece el fragmento de
vendorscomo un fragmento común. -
El complemento procesa la porción común de los
vendors:-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
entry1yentry2usanjquerypara que el módulo se elimine de estos fragmentos (tenga en cuenta que no se agrega al fragmento devendorsporque el fragmento devendorsya lo contiene). -
El fragmento de
vendorsse marca como un fragmento deentrymientras que los fragmentos deentry1yentry2se identifican comoentry.
-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
-
Finalmente, dado que el fragmento de
vendorses un fragmento deentry, contiene el tiempo de ejecución y los módulosjquery/jquery_plugin.
CASO 3:
-
Hay 3 fragmentos de
entry(entry1,entry2yvendors). -
La configuración establece el fragmento de
vendorsy el fragmento demanifestcomo fragmentos comunes. -
El complemento crea el fragmento de
manifestya que no existe. -
El complemento procesa la porción común de los
vendors:-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
entry1yentry2usanjquerypara que el módulo se elimine de estos fragmentos (tenga en cuenta que no se agrega al fragmento devendorsporque el fragmento devendorsya lo contiene). -
El fragmento de
vendorsse marca como un fragmento deentrymientras que los fragmentos deentry1yentry2se identifican comoentry.
-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
-
El complemento procesa el fragmento común
manifest(dado que el fragmento no existe, se crea):- Recopila los módulos que se usan más de una vez en los otros fragmentos: como no hay módulos usados más de una vez, no se mueve ningún módulo.
-
El fragmento de
manifestse marca como fragmento deentrymientras que laentry1, laentry2y losvendorsestán sin marcar comoentry.
-
Finalmente, dado que el fragmento de
manifestes un fragmento deentry, contiene el tiempo de ejecución.
Espero eso ayude.