Questo post fa parte di una serie dedicata ad Aurelia e ASP.NET Core.
Quando ormai il morale della ciurma cominciava a vacillare, ecco finalmente un urlo straziato dalla coffa: Aurelia!!!
Ebbene sì, siamo giunti finalmente al punto in cui siamo pronti ad aggiungere Aurelia al nostro progetto utilizzando ovviamente NPM e JSPM.
Aggiungere NPM
Per prima cosa dobbiamo quindi aggiungere NPM e, con il supporto fornito da Visual Studio, la cosa è estremamente facile. Ci è sufficiente aggiungere un nuovo npm Configuration File al progetto, di tutto il resto si occupa l'ambiente di sviluppo:
Il file – package.json - è di per se stesso abbastanza scarno e possiamo per ora concentrare la nostra attenzione sulla sezione devDependencies dove è possibile specificare le dipendenze da quei pacchetti che sono utili nella fase di sviluppo del progetto, esattamente il caso di JSPM:
Aggiungere JSPM
L'aggiunta di JSPM è infatti ancora più semplice: come abbiamo visto qualche post fa per il nuovo project.json – che contiene le dipendenze NuGet (ma non vi abituate troppo, in Visual Studio 2017 andrà purtroppo in pensione prematura) – anche package.json supporta l'editing manuale con Intellisense, per cui tutto quello che dobbiamo fare è digitare "jspm" all'interno della sezione devDependencies e selezionare la versione che ci interessa referenziare (al momento la 0.16.48). In seguito al salvataggio del file, Visual Studio si occuperà di scaricare il pacchetto e le eventuali relative dipendenze:
Con un po' di pazienza avremo alla fine JSPM elencato tra le dipendenze del progetto. Al momento vi sconsiglio di cliccare sulla freccia accanto al pacchetto JSPM, perché è come aprire il vaso di Pandora (e non fate come Julia Roberts in Nothing Hill… non aprite quella porta):
Aggiungere Aurelia
JSPM deve essere configurato prima di poter essere usato, ma tale inizializzazione può essere fatta congiuntamente con il download del primo pacchetto, ed è esattamente ciò che faremo.
Visual Studio non dispone (ad oggi) di un supporto nativo per JSPM come per NPM o Bower. Come conseguenza, l'installazione dei vari pacchetti dovrebbe essere fatta a riga di comando. In alternativa vi suggerisco di scaricare la comodissima estensione partorita dalla mente sempre viva di Mads Kristensen: si tratta in un Package Installer che consente di installare pacchetti da diverse fonti, wrappando in pratica le chiamate a riga di comando in una maschera semplice ma efficacie:
A seguito dell'installazione dell'estensione avremo disponibile una nuova voce Quick Install Package… nel menu contestuale del progetto (attivabile anche con lo shortcut Shift+Alt+0):
Clicchiamo sulla voce e nella maschera risultante selezioniamo JSPM come fonte, digitiamo "aurelia-framework" come pacchetto e clicchiamo infine su Install:
Come detto alla prima installazione sarà necessario configurare JSPM rispondendo ad una serie di semplici domande:
- La prima domanda ci chiede se vogliamo registrare le proprietà di JSPM che saranno aggiunte al file package.json di NPM all'interno di un nodo jspm. Confermiamo l'impostazione di default sì;
- La seconda domanda ci chiede di indicare quale sia la web root del nostro progetto. Per quanto abbiamo detto in un precedente post è ovvio che per i progetti ASP.NET Core dobbiamo impostare ./wwwroot;
- È la volta di configurare la cartella in cui JPSM scaricherà i pacchetti che aggiungeremo al progetto (come ad esempio in questo caso Aurelia). Il default è wwwroot/jspm_packages. Potete scegliere questa cartella secondo le vostre preferenze, io per ora imposterò wwwroot/_libs;
- È ora il momento della posizione del file config.js che servirà a JSPM per gestire i pacchetti scaricati. Confermiamo il default wwwroot/config.js (e confermiamo anche la sua successiva creazione in automatico);
- La sesta domanda ci chiede di indicare la URL con cui il nostro sito è esposto pubblicamente. Confermiamo il default /;
- Siamo alla fine ed è sufficiente confermare il default anche per le ultime due domande: sì, vogliamo usare un transpiler (cioè un meccanismo per "invecchiare" il codice JavaScript in modo da renderlo compatibile con i browser più anziani) e in particolare vogliamo usare Babel.
Al termine della configurazione il download del pacchetto aurelia-framework (e di tutti i pacchetti da cui esso dipende, Aurelia è strutturato in maniera molto granulare, come ASP.NET Core) inizierà automaticamente:
Al termine del download, nella cartella _libs o in qualunque altra cartella voi abbiate scelto in fase di configurazione, potremo trovare i file JavaScript che compongono il cuore del framework Aurelia (un secondo vaso di Pandora che per ora ignoriamo come il primo).
Se vi accorgete che qualcosa non vi convince nel modo in cui avete impostato JSPM non è mai troppo tardi per tornare indietro. La configurazione è infatti disponibile in parte del file package.json di NPM e in parte nel file config.js di JSPM (che potrebbe ovviamente chiamarsi diversamente che avete scelto di modificare il nome di default).
Prima di poter vedere Aurelia in azione abbiamo bisogno di installare un secondo pacchetto chiamato aurelia-bootstrapper del quale avremo modo di parlare meglio in un prossimo post. Ormai sappiamo come fare: Shift+Alt+0 e via:
Hello Aurelia!
I preliminari sono finiti (il che vuol dire che tempo 5 minuti e saremo giunti alla conclusione): possiamo mettere in piedi la nostra demo. Come tutti i framework SPA, Aurelia ha bisogno di un punto di ingresso, una URL che venga servita da ASP.NET Core come una qualunque risorsa "server" e che contenga al suo interno il codice necessario al framework per mettersi in azione e prendersi carico delle successive richieste sul "client". Per il nostro esempio riutilizzeremo il file index.html, modificando il body per aggiungere il codice necessario ad attivare Aurelia:
Ci sono un po' di cose da notare in questo frammento di codice:
- Il primo tag script serve ad importare la libreria SystemJS che si occupa del caricamento asincrono on-demand dei vari moduli che comporranno la nostra applicazione (quelli di Aurelia, di altre librerie che potremmo voler usare come ad esempio Bootstrap e ovviamente quelli che scriveremo noi stessi per implementare la logica applicativa). Come detto in un precedente post, JSPM integra infatti le funzionalità di un package manager con quelle di un module loader per fornire una soluzione completa;
- Il secondo tag script serve ad importate il file di configurazione di JSPM che contiene alcune delle impostazioni che abbiamo selezionato in fase di inizializzazione e, soprattutto, l'elenco dei pacchetti aggiunti all'applicazione con il rispettivo albero di dipendenze;
- Il terzo tag script utilizza SystemJS per caricare il bootstrapper di Aurelia che si occuperà di caricare e attivare il framework;
- L'attributo aurelia-app con cui abbiano decorato il body serve infine ad indicare ad Aurelia in quale parte della pagina vogliamo caricare la nostra SPA.
Abbiamo già accennato nel post precedente che Aurelia è basato su MVVM. Non ci sorprende quindi che una "pagina" di Aurelia è composta da una View (un file HTML) e da un ViewModel (un file JavaScript). Come vedremo nei prossimi post questa coppia di elementi deve rispettare alcune semplici (e soprattutto logiche) regole nelle quali al momento non voglio addentrarmi perché dovremmo altrimenti ulteriormente rimandare il nostro F5 e finirei col perdere una certa scommessa con un certo personaggio.
Al momento limitiamoci a creare un nuovo file JavaScript app.js sotto wwwroot che funga da ViewModel con il seguente contenuto:
Anche la View (il file HTML app.html) sarà decisamente minimale:
In definitiva il nostro progetto dovrebbe alla fine essere strutturato più o meno così:
Siamo pronti! F5 e via:
Indubbiamente il risultato è quello atteso, ma è evidente che qualcosa di magico deve essere successo dietro le quinte perché quello che abbiamo scritto in index.html, app.js e app.html non è assolutamente sufficiente a garantire quello che vediamo. Se apriamo il DOM Explorer ecco come risulta l'HTML ricevuto dal browser:
Un bel po' di cose sono successe e alcune domande richiedono una risposta:
- Come ha fatto Aurelia a capire che volevamo mostrare il contenuto della pagina app?
- Che fine ha fatto il tag template che era nel file app.html?
- Cos'è la strana sintassi che abbiamo usato nel file app.js?
Le risposte a queste domande si possono sintetizzare in tre concetti – convention-over-configuration, HTML5 standard e ES2016 – che saranno l'argomento principale dei prossimi post.
Happy coding!
P.S. Il codice sorgente è disponibile su GitHub, basta scaricare la release con lo stesso nome del post (Hello Aurelia! in questo caso).