Tra le novità introdotte nell’ultima versione ES6 ECMAScript 2015, sicuramente va sottolineato il supporto nativo dei moduli. Che cos’è un modulo? Un modulo è semplicemente un file. Uno script è un modulo. La regola vuole che esista solo un modulo per file e un file contiene un solo modulo. I moduli possono caricarsi a vicenda e utilizzare speciali direttive export e import per scambiarsi funzionalità, chiamando le funzioni da un modulo all’altro. Per chi volesse approfondire, in questo articolo si parla in maniera abbastanza approfondita della modularità in Javascript.
Nella maggior parte dei linguaggi di programmazione (incluso ECMAScript 2015), è possibile dividere il codice in più file e importare specifici file all’interno di altri file per utilizzare le funzionalità in essi contenute. In questo modo si evita la ridondanza e si ottimizza la riusabilità del codice. Questa caratteristica, fino a poco tempo fa, non era integrata nel browser, e quindi per ovviare a questo problema nacquero i Bundler, degli strumenti utilizzati dagli sviluppatori frontend per raggruppare i moduli JavaScript in un unico file JavaScript che può essere eseguito nel browser.
Il bundler aiuta a gestire la relazione di dipendenza caricando i moduli in ordine di dipendenza. Per esempio, immaginiamo di creare un’applicazione Web, che è composta da più file JavaScript. Questi file sappiamo che vanno aggiunti alla pagina con il tag <script>, quindi:
<html> <script src="/libs/foo.js"></script> <script src="/libs/uno.js"></script> <script src="/libs/due.js"></script> <script src="/libs/tre.js"></script> <script src="/libs/qua.js"></script> </html>
Senza un module loader e i bundler, potremmo combinare i file JS manualmente (abbastanza complicato) o caricarli attraverso innumerevoli tag <script>, ma ciò presenta diversi svantaggi:
- È necessario tenere traccia dell’ordine corretto in cui i file devono essere caricati, inclusi i file che dipendono da quali altri file e assicurandosi di non includere file non necessari.
- Più <script> significa più chiamate al server per caricare tutto il codice, che peggiora le prestazioni (nel caso sopra, 5 richieste).
La maggior parte dei bundler di moduli si integra anche direttamente con npm o Bower per consentire di aggiungere facilmente dipendenze di terze parti all’applicazione. Basta installarli e inserire una riga di codice per importarli nell’applicazione. Opportunamente configurato, il bundler può unificare il codice di terze parti combinato con il codice dell’applicazione oppure avere il codice di terze parti in un file separato, in modo che quando verrà aggiornato il codice dell’applicazione, gli utenti non dovranno scaricare anche il codice vendor quando dovranno aggiornare la cache del solo codice dell’applicazione.
Con il bundle, questi file verrebbero combinati in un unico file JS, e ciò porterebbe a una semplificazione sia dal punto di vista del codice, che dal punto di vista delle richieste.
<html> <script src="/dist/bundle.js"></script> </html>
Ma come generiamo il file bundle.js? Alcuni bundler più comuni sono: webpack, rollup, fusebox, parcel.
Webpack
In questo articolo ci concentreremo su webpack , uno strumento scritto da Tobias Koppers , che nel tempo è cresciuto fino a diventare uno strumento importante all’interno della toolchain JavaScript, spesso utilizzato in progetti grandi e piccoli. Perché scegliere webpack rispetto agli altri?
- E’ relativamente più nuovo rispetto ai suoi predecessori, il che è un vantaggio in quanto aggira o evita le carenze e i problemi dei bundler concorrenti
- E’ semplice da usare: se dobbiamo raggruppare solo un mucchio di file JS senza altri fronzoli, non ci sarà neppure bisogno di un file di configurazione
- E’ molto potente e potrebbe essere l’unico strumento di sviluppo di cui avremo bisogno
- E’ supportato da una grande comunità che può aiutarci quando rimaniamo bloccato
Per installare Webpack, è necessario avere già installato Node.js e npm. Ci sono due modi per installare webpack: globalmente o localmente. Se lo installiamo a livello globale, possiamo usarlo indipendentemente dalla directory in cui ti trovi, ma non sarà incluso come dipendenza nel progetto e non potremo passare da una versione all’altra di Webpack per progetti diversi. In alternativa, è possibile installare i pacchetti CLI localmente e utilizzare percorsi relativi o script npm per eseguire il pacchetto.
Per prima cosa: apriamo una finestra di shell e creiamo una directory per il progetto in cui possiamo sperimentare e conoscere Webpack. Una volta all’interno della directory del progetto, inizializziamo il progetto con npm init. Seguiamo e rispondiamo alle varie richieste tenendo conto che le informazioni fornite non sono così importanti, a meno che non prevediamo di pubblicare il progetto su npm. Il comando init crea un file chiamato package.json: le dipendente verranno scritte li dentro. Usiamo adesso npm per installare webpack e webpack-cli come dipendenza con:
npm install webpack webpack-cli --save-dev
( l’opzione –save-dev indica a npm che si tratta di una dipendenza di sviluppo).
Prima di poter utilizzare webpack, dovremmo avere una semplice applicazione su cui usarlo. Proviamo ad installare la libreria Lodash in modo da avere una dipendenza da caricare nella nostra app. La libreria va installata con npm, che si occuperà di scaricare la libreria dal repository nella cartella node_modules e di aggiornare il blocco delle dipendenze del file package.json.
npm install lodash -S
Creiamo una cartella chiamata src e all’interno creeremo il file main.js. Il codice da inserire all’interno del file JS è il seguente:
var map = require('lodash/map'); function quadrato(n) { return n*n; } console.log(map([1,2,3,4,5,6], quadrato));
Avviando questo script dalla finestra di shell con il comando node src/main.js, dovrebbe mostrare questo output: [ 1, 4, 9, 16, 25, 36 ]. Abbiamo utilizzato la funzione map di Lodash per creare un array e applicare la funzione quadrato. Adesso che abbiamo testato la nostra app, proviamo a raggruppare gli script con webpack.
“Pacchettizziamo” il tutto
Il modo più semplice per iniziare a utilizzare Webpack è semplicemente eseguirlo dalla riga di comando, anziché creare un file di configurazione. Webpack leggerà il file di input, traccerà il suo albero delle dipendenze, richiamerà e combinerà tutti i file insieme in un unico file e creerà il file nella posizione specificata come percorso di output di default (folder dist). Per questo esempio, l’input è src/main.js e l’output sarà dist/main.js.
Nel file package.json, basta aggiungere la seguente riga di codice “build”: “webpack –mode=development ./src/main.js” nel blocco scripts in questo modo:
… "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --mode=development ./src/main.js" } …
Dopo aver salvato il file, dalla finestra di shell eseguire il comando:
npm run build
Il Webpack dovrebbe adesso pacchettizzare il tutto in un file chiamato dist/main.js. Se proviamo ad eseguire con node il file node dist/main.js, dovremmo vedere lo stesso risultato del precedente script in src. Potremmo rendere i nostri script di build un po’ più professionali, aggiungendo qualche altro script per eseguire il bundle pacchettizzato.
Aggiungiamo quindi alcune righe al file package.json in questo modo:
... "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --mode=development ./src/main.js", "execute": "node dist/main.js", "start": "npm run build -s && npm run execute -s" }, ...
A questo punto, per avviare lo script, dovremmo eseguire il comando npm run start, che a sua volta esegue in maniera sequenziale i comandi npm run build e npm run execute.
Nel prossimo articolo vedremo invece come configurare correttamente il file di configurazione di webpack.