bit webpack: ottenere il massimo da CommonsChunkPlugin ()

Di tanto in tanto, il core team del webpack ama coinvolgere la community su Twitter e condividere frammenti di conoscenza in modo divertente e informativo.

Questa volta, le "regole del gioco" erano semplici. Installa webpack-bundle-analyser, genera un'immagine colorata di fantasia di tutti i tuoi bundle e condividila con me. In cambio, il team del webpack si è offerto di aiutare a identificare eventuali potenziali problemi che potremmo individuare!

Cosa abbiamo trovato?

Il tema più comune era la duplicazione del codice: librerie, componenti, codice erano duplicati su più bundle [sync or async]!

Caso 1: molti bundle di fornitori con codice duplicato

Swizec Teller è stato così gentile da condividere una delle sue build (che in realtà è costruita per oltre 8-9 applicazioni standalone a pagina singola). Ho scelto questo esempio tra tutti perché ci sono così tante grandi tecniche che possiamo identificare da esso. Quindi diamo un'occhiata a questo in modo più dettagliato:

Più vicino all'icona

Da questo possiamo dedurre un bel po 'di cose (senza guardare alla configurazione effettiva).

Ogni app a pagina singola utilizza un nuovo CommonsChunkPlugin destinato solo a quel punto di ingresso e al suo codice fornitore. Questo crea un pacchetto con solo i moduli che provengono dalla cartella node_modules e un altro pacchetto con solo il codice dell'applicazione. La parte di configurazione è stata persino fornita:

Object.keys (activeApps)
  .map (app => new webpack.optimize.CommonsChunkPlugin ({
    nome: `$ {app} _vendor`,
    blocchi: [app],
    minChunks: isVendor
  }))

Molto probabilmente la variabile activeApps rappresenta ciascuno dei singoli punti di ingresso.

Aree di opportunità

Di seguito sono riportate alcune aree che ho cerchiato e che potrebbero essere migliorate.

Memorizzazione nella cache "Meta"

Quello che vediamo sopra sono molte grandi librerie come momentjs, lodash e jquery utilizzate in 6 o più bundle di fornitori. La strategia per aggiungere tutti i fornitori in un pacchetto separato è buona, ma dovremmo anche applicare la stessa strategia a tutti i pacchetti di fornitori.

Ho suggerito che Swizec aggiungesse quanto segue alla fine del suo array di plugin:

nuovo webpack.optimize.CommonsChunkPlugin ({
  bambini: vero,
  minChunks: 6
})

Quello che stiamo dicendo al webpack è il seguente:

Ehi webpack, guarda tutti i blocchi (compresi quelli del fornitore che sono stati generati) e sposta tutti i moduli che si verificano in almeno 6 blocchi in un file separato.

Come puoi vedere ora, tutti questi moduli sono stati estratti in un file separato e, soprattutto, Swizec ha riferito che questo ha ridotto le dimensioni complessive dell'applicazione del 17%!

Caso due: fornitori duplicati su blocchi asincroni:

Quindi questa quantità di duplicazione non era così grave in termini di dimensioni complessive del codice, tuttavia, quando guardi l'immagine a dimensione intera qui sotto, puoi vedere gli stessi 3 moduli esatti su ogni blocco asincrono.

I blocchi asincroni sono quelli che contengono

Come puoi vedere sopra, gli stessi 2–3 componenti vengono utilizzati in tutti i 40-50 pacchetti asincroni. Quindi, come possiamo risolverlo con CommonsChunkPlugin?

Crea un pezzo comune asincrono

La tecnica sarà molto simile alla prima, tuttavia dovremo impostare la proprietà asincrona nell'opzione di configurazione, su true come mostrato di seguito:

nuovo webpack.optimize.CommonsChunkPlugin ({
  asincrono: vero,
  bambini: vero,
  nome file: "commonlazy.js"
});

Allo stesso modo - webpack scansiona tutti i blocchi e cerca i moduli più comuni. Da asincrono: vero, verranno scansionati solo i bundle di suddivisione del codice. Poiché non abbiamo specificato minChunks il valore predefinito è 3. Quindi ciò che viene detto al webpack è:

Ehi webpack, guarda attraverso tutti i normali blocchi [aka caricati pigri], e se trovi lo stesso modulo che appare su 3 o più blocchi, quindi separalo in un pezzo separato di beni asincroni.

Ecco quale è stato il risultato:

Ora i blocchi asincroni sono estremamente piccoli e tutto quel codice è stato aggregato in un file chiamato commonlazy.js. Poiché questi bundle erano già piuttosto piccoli, l'impatto sulla dimensione non era molto evidente fino alla seconda visita. Ora vengono spediti molti meno dati per pacchetto suddiviso in codici e stiamo risparmiando tempo e tempo di caricamento degli utenti inserendo quei moduli comuni in un blocco separato memorizzabile nella cache.

Più controllo: funzione minChunks

E se volessi avere un maggiore controllo? Ci sono scenari in cui non si desidera avere un singolo pacchetto condiviso perché non tutti i blocchi pigri / di ingresso possono usarlo. Anche la proprietà minChunks ha una funzione !! Questo può essere il tuo "predicato di filtro" per quali moduli vengono aggiunti al pacchetto appena creato. Di seguito sono riportati esempi di

nuovo webpack.optimize.CommonsChunkPlugin ({
  nome file: "lodash-moment-shared-bundle.js",
  minChunks: function (module, count) {
    return module.resource && /lodash|moment/.test(module.resource) && count> = 3
  }
})

L'esempio sopra dice:

Yo webpack, quando ti imbatti in un modulo il cui percorso assoluto corrisponde a lodash o momentjs, e si verifica attraverso 3 voci / blocchi separati, quindi estrai quei moduli in un pacchetto separato.

Puoi applicare questo stesso comportamento ai bundle asincroni impostando anche `async: true`!

Anche il controllo del moar

Con questo minChunks è possibile creare sottoinsiemi più piccoli di fornitori memorizzabili nella cache per voci e pacchetti specifici. Alla fine, potresti finire con qualcosa che assomiglia a questo:

function lodashMomentModuleFilter (module, count) {
  return module.resource && /lodash|moment/.test(module.resource) && count> = 2;
}
function immutableReactModuleFilter (module, count) {
  return module.resource && /immutable|react/.test(module.resource) && count> = 4
}
nuovo webpack.optimize.CommonsChunkPlugin ({
  nome file: "lodash-moment-shared-bundle.js",
  minChunks: lodashMomentModuleFilter
})
nuovo webpack.optimize.CommonsChunkPlugin ({
  nome file: "immutable -eag-shared-bundle.js",
  minChunks: immutableReactModuleFilter
})
EDIT (1 aprile): ho dichiarato che potresti usare il nome file con minChunks, ma lo impediamo ora dal webpack 2.3.2+.

Non c'è proiettile d'argento!

CommonsChunkPlugin () può essere potente, ma tieni presente che ognuno di questi esempi è adattato all'applicazione a cui è applicato. Quindi, prima di copiare questi frammenti, consulta prima i consigli di Sam Saccone, Paul Irish e MPDIA per assicurarti di applicare la soluzione giusta.

Comprendi sempre il tuo processo prima di applicare le soluzioni!

Dove posso trovare altri esempi?

Questi sono solo alcuni esempi di opzioni e usi per CommonsChunkPlugin (). Per saperne di più, dai un'occhiata alla nostra directory / samples nel nostro repository GitHub core webpack / webpack! Se hai una grande idea di più, sentiti libero e invia una richiesta pull!

Non hai tempo per contribuire? Vuoi restituire in altri modi? Diventa un sostenitore o sponsor del webpack donando al nostro collettivo aperto. Open Collective non solo aiuta a supportare il Core Team, ma supporta anche i collaboratori che hanno trascorso molto tempo a migliorare la nostra organizzazione nel tempo libero! ❤