webpack è un cosiddetto "static module bundler", prende in input tutto un insieme di moduli
"sorgenti", che possono essere file JS con tutte le loro dipendenze, immagini, file TS, CSS, SASS/LESS, font,
etc. e crea in
output dei cosiddetti "bundle" (anche più di uno, nel caso si può parlare di "chunks" che compongono il
bundle o più semplicemente di bundle multipli) che sono dei file statici interpretabili dal browser.
Ha parzialmente rimpiazzato i task runner quali Grunt e Gulp.
I principali componenti sono:
entry-point: per default è "src/index.js" il file sorgente da cui parte il processo di
compilazione
output: è la cartella "dist" che contiene il risultato della compilazione
loaders: sono quei package che permettono a webpack di generare il risultato finale
plugins: sono appunto dei plugin che aggiungono funzionalità alla fase di generazione del
bundle
Creo una nuova cartella di progetto e inizializzo il nuovo progetto:
>npm init -y
installo webpack e la sua CLI come dipendenze di sviluppo (devDependencies):
>npm i webpack webpack-cli --save-dev
La struttura delle cartelle del mio progetto inizialmente sarà più o meno questa:
progetto
|______ dist
|______ src
index.js
|______ node_modules
package.json
package-lock.json
webpack.config.js
La cartella src conterrà i moduli sorgenti, incluso l'entry-point.
La cartella dist è quella di output che contiene i bundle generati.
"webpack.config.js" è un file di configurazione da creare a mano.
webpack.config.js è un file di configurazione da posizionare generalmente sotto la
root di progetto.
Nel package.json inserisco questo script:
"build" : "webpack"
poi dalla CLI dò il comando
>npm run build
in questo modo invoco webpack che compilerà i miei sorgenti e genererà un bundle nella cartella
dist, utilizzando le opzioni specificate nel file di configurazione.
Ad esempio se voglio utilizzare nel mio progetto dei files .css, dovrò installare i loader necessari (sono i
package style-css e css-loader) e poi nel file di configurazione devo dire a webpack di
utilizzarli (con la
proprietà "use") e per quali tipi di file (con la proprità "test" , che accetta una RegExp).
Per poter utilizzare i file .scss nel progetto sono necessari i loaders: sass-loader e
sass.
Ogni file creato dalla build è chiamato "bundle" o "chunk". Se voglio generare più chunks devo specificarlo
nel file di configurazione, in particolare nella proprietà
"output". E' possibile generare i nomi dei file (dei chunks) in maniera "dinamica" utilizzando una variabile
[name].
I plugin forniscono delle funzionalità aggiuntive in fase di generazione della build.
Esempi di plugin:
html-webpack-plugin: gestisce automaticamente l'elenco dei "chunks" che includo nel mio file
index.html, cioè in fase di generazione va ad inserire in automatico nel file index.html l'elenco dei chunks
generati (inserisce i relativi tag "
<script></script>" in fondo al file prima della chiusura del
</body>. )
clean-webpack-plugin: cancella tutti i file "vecchi" che non serveno a webpack dalla cartella
dist.
Esistono molti altri plugins (documentazione
ufficiale )
Inserendo questa proprietà nel file di configurazione:
devtool : "inline-source-map"
è possibile avere delle info aggiuntive utili quando ci sono degli errori o si deve debuggare. Vengono
generate delle "mappe" del codice sorgente, che mi permetteno ad esempio di sapere esattamente quale porzione
di codice ha dato errore. Nei devtools del browser (F12), sia sotto "Console" che sotto "Sources" ho delle
info più
specifiche. Sotto "Sources" trovo tutti i file del mio progetto, sia i sorgenti che quelli ottenuti dalla
compilazione.
L'opzione "WATCH" permette di avere webpack in ascolto di eventuali modifiche sui file sorgente e nel caso
eseguire automaticamente una nuova build.
E' necessario inserire un nuovo script in package.json:
"watch": "webpack --watch"
dopodichè, dalla CLI, anzichè
>npm run build
darò
>npm run watch
NOTA: ad oggi 23/10/2020 sulla versione 4 di webpack-cli, c'è un baco per cui vengono generati dei warning
(DeprecationWarning, info a questo link)
In alternativa, se inserisco, nel file di configurazione, la proprietà:
watch: true
il comando >npm run build compila e poi và in watch.
Per ottenere un server locale sul quale hostare il progetto, bisogna installare questo package:
>npm i --save-dev webpack-dev-server
poi nel file package.json aggiungo questo script:
"start": "webpack serve"
e infine, da CLI, dò il comando:
>npm start
Verrà creato un server locale accessibile sulla porta 8080 (default): http://localhost:8080
Ad ogni modifica dei file sorgenti ci sarà un " live reload" e la pagina risulterà aggiornata praticamente in
tempo reale con le modifiche appena inserite.
NOTA BENE: webpack-dev-server non scrive nessun file di output dopo la compilazione.
Invece, tiene i bundle files generati in memoria e li serve tramite il server locale, per cui nella cartella
"dist" non avrò nessun bundle aggiornato. Per aggiornare i file in "dist" devo dare un comando di "build" o
"watch".
Questo bottone, al click, invoca una funzione che scrive in Console una stringa.
Il codice che crea il bottone e gestisce il click è definito nell'entry point file (index.js), mentre
la funzione che viene richiamata è definita in un altro modulo (module1.js) che viene "importato" dal modulo
chiamante. Vedi codice nella repo.