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.js
que contiene el código completo deentry1.js
yjquery
y contiene su propio tiempo de ejecución -
entry2.bundle.js
que contiene el código completo deentry2.js
yjquery
y contiene su propio tiempo de ejecución -
vendors.bundle.js
que contiene el código completo dejquery
ysome_jquery_plugin
y 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.js
que contiene el código completo deentry1.js
, un requisito parajquery
y no contiene el tiempo de ejecución -
entry2.bundle.js
que contiene el código completo deentry2.js
, un requisito parajquery
y no contiene el tiempo de ejecución -
vendors.bundle.js
que contiene el código completo desome_jquery_plugin
, un requisito parajquery
y no contiene el tiempo de ejecución -
commons.bundle.js
que contiene el código completo dejquery
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
commons
. Bastante bien pero no ideal. -
-
CASO 2: Si paso
{ name : ''vendors'' }
terminaré con los siguientes archivos de paquete:-
entry1.bundle.js
que contiene el código completo deentry1.js
, un requisito parajquery
y no contiene el tiempo de ejecución -
entry2.bundle.js
que contiene el código completo deentry2.js
, un requisito parajquery
y no contiene el tiempo de ejecución -
vendors.bundle.js
que contiene el código completo dejquery
ysome_jquery_plugin
y 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.js
que contiene el código completo deentry1.js
, un requisito parajquery
y no contiene el tiempo de ejecución -
entry2.bundle.js
que contiene el código completo deentry2.js
, un requisito parajquery
y no contiene el tiempo de ejecución -
vendors.bundle.js
que contiene el código completo dejquery
ysome_jquery_plugin
y no contiene el tiempo de ejecución -
manifest.bundle.js
que 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
vendors
contiene tanto el código común (jquery
) como lo que quedó de la entrada devendors
(some_jquery_plugin
)? Según tengo entendido, lo que hizoCommonsChunkPlugin
aquí fue que recopiló el código común (jquery
), y como loCommonsChunkPlugin
al 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 tantojquery
comosome_jquery_plugin
, cuandojquery
es claramente una dependencia común, y por qué el archivomanifest.bundle.js
generado 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
,entry2
yvendors
). -
La configuración establece el fragmento de
commons
como 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
,entry2
y losvendors
usanjquery
por lo que el módulo se elimina de estos fragmentos y se agrega al fragmentocommons
. -
El fragmento de
commons
se marca como un fragmento deentry
mientras que los fragmentos deentry1
,entry2
yvendors
está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
commons
es un fragmento deentry
, contiene el tiempo de ejecución y el módulojquery
.
CASO 2:
-
Hay 3 fragmentos de
entry
(entry1
,entry2
yvendors
). -
La configuración establece el fragmento de
vendors
como 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:
entry1
yentry2
usanjquery
para que el módulo se elimine de estos fragmentos (tenga en cuenta que no se agrega al fragmento devendors
porque el fragmento devendors
ya lo contiene). -
El fragmento de
vendors
se marca como un fragmento deentry
mientras que los fragmentos deentry1
yentry2
se identifican comoentry
.
-
Recopila los módulos que se usan más de una vez en los otros fragmentos:
-
Finalmente, dado que el fragmento de
vendors
es un fragmento deentry
, contiene el tiempo de ejecución y los módulosjquery
/jquery_plugin
.
CASO 3:
-
Hay 3 fragmentos de
entry
(entry1
,entry2
yvendors
). -
La configuración establece el fragmento de
vendors
y el fragmento demanifest
como fragmentos comunes. -
El complemento crea el fragmento de
manifest
ya 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:
entry1
yentry2
usanjquery
para que el módulo se elimine de estos fragmentos (tenga en cuenta que no se agrega al fragmento devendors
porque el fragmento devendors
ya lo contiene). -
El fragmento de
vendors
se marca como un fragmento deentry
mientras que los fragmentos deentry1
yentry2
se 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
manifest
se marca como fragmento deentry
mientras que laentry1
, laentry2
y losvendors
están sin marcar comoentry
.
-
Finalmente, dado que el fragmento de
manifest
es un fragmento deentry
, contiene el tiempo de ejecución.
Espero eso ayude.