Creare un’applicazione Aurelia con la dotnet CLI e i JavaScriptServices

Buone notizie per chi come me ha scelto Aurelia come framework di riferimento per scrivere Single Page Application. Un po' alla volta la creatura di Rob Eisenberg si sta ritagliando il suo spazio ed è ora un firstclass citizen nell'ultima versione della dotnet CLI, quella disponibile nella SDK 1.0 rc4 build 004771.

Per i pochi che si trovassero spaesati, stiamo parlando del tool a riga di comando (CommandLine Interface) che consente di eseguire tutte le operazioni legate alla generazione, esecuzione e pubblicazione di un applicativo basato su .NET Core.

È da qualche giorno disponibile una serie di pacchetti NuGet che estende i template di default della CLI consentendo di generare SPA basate sui principali framework presenti sul mercato. Accanto ad Angular e React fa bella mostra di sé anche il template per generare applicazioni basate su Aurelia. Vediamo cosa dobbiamo fare per utilizzarlo.

Come prima cosa dobbiamo assicurarci di avere installata la versione di SDK corrispondente alla build 004771 o superiore che potete eventualmente scaricare dal link precedente:

Dopo averlo installato, aprendo un prompt dei comandi e digitando dotnet --version dovreste ricevere l'indicazione 1.0.0-rc4-004771. A questo punto possiamo digitare dotnet new --help per verificare quali siano i template disponibili per la creazione di un nuovo progetto. Se avete appena installato la CLI potreste dover attendere un po'per il popolamento della cache locale:

Di base dovreste avere disponibili di seguenti template:

Per cui potremmo ad esempio digitare dotnet new web per creare una nuova applicazione ASP.NET Core vuota da usare come base per i nostri sviluppi.

Per installare i template dedicati alle applicazioni SPA dobbiamo invece digitare dotnet new --install Microsoft.AspNetCore.SpaTemplates::*:

Dopo aver installato un po' di package assortiti (nel mio caso 111) i nuovi template dovrebbero essere a vostra disposizione:

Proviamo subito a vedere "l'effetto che fa". Spostiamoci nella cartella dove vogliamo creare il progetto e digitiamo prima dotnet new aurelia e quindi dotnet restore. Il primo comando crea il progetto a partire dal template, il secondo effettua il restore dei due pacchetti NuGet utilizzati (NodeServices e SpaServices):

Il template contiene al suo interno il file di configurazione project.json che elenca tutti i pacchetti NPM necessari. Per ripristinarli è sufficiente digitare npm install dallo stesso prompt dei comandi. Dopo un po' di attesa abbiamo finalmente il nostro progetto pronto e possiamo lanciarlo con il comando dotnet run. Per default il progetto creato si mette in ascolto sulla porta 5000 ed è quindi sufficiente digitare http://localhost:5000 in un qualsiasi browser per navigarlo:

Ci sono alcune differenze da notare rispetto al progetto che sto portando avanti nella mia serie su Aurelia:

  • Il progetto generato dal template è per Visual Studio 2017. Come conseguenza il file di progetto xproj è stato sostituito dal file csproj e il file project.json è sparito. Per modificare il progetto potete quindi usare Visual Studio 2017, Visual Studio Code o ovviamente il vostro editor preferito. Il progetto è inoltre basato su ASP.NET Core 1.1 (invece che sull'1.0 come nella mia serie), ma questo è un aspetto che non al momento ha impatti e che affronteremo a breve anche noi;
  • Come si vede nello screenshot, il progetto così lanciato gira in ambiente di produzione, a differenza di quanto succede lanciando il progetto da dentro Visual Studio. Questo è dovuto al fatto che Visual Studio definisce per noi la variabile ASPNETCORE_ENVIRONMENT e la imposta al valore Development. Per ottenere lo stesso comportamento a riga di comando dobbiamo definire manualmente la stessa variabile, andando nell'apposita sezione del pannello di controllo o utilizzando il comando setx ASPNETCORE_ENVIRONMENT "Development" (in questo caso è necessario aprire un nuovo prompt dei comandi per "vedere" la nuova variabile);
  • Come avevamo avuto modo di dire, Aurelia supporta diversi package manager. Nella nostra serie stiamo usando JSPM mentre il progetto generato dal template per uniformità tra i vari framework utilizza invece Webpack. Il progetto include anche i concetti di bundling e minification che ancora non abbiamo affrontato nella serie, e potrebbe quindi essere un po' spiazzante il fatto di non trovare nella cartella wwwroot nessuno dei ViewModel e delle View che ci aspetteremmo di trovare (a dire il vero i file html mancano del tutto). Non è il momento di spiegare nel dettaglio il funzionamento di Webpack, in ogni caso se volete modificare il progetto i file che vi interessano si trovano nella cartella ClientApp;
  • Il progetto usa TypeScript invece che ES2015 per definire i ViewModel. Come vedrete se vi addentrerete tra i file, le differenze sono minime e si concretizzano soprattutto nella possibilità di tipizzare variabili e parametri. Se guardate in wwwroot vi accorgete che gli unici due file JavaScript (oltre a essere apparentemente incomprensibili) sono invece caratterizzati da una sintassi ES5. Questo è il risultato dell'uso del bundling di Webpack per ottimizzare prestazioni e compatibilità. Per capire meglio di cosa parlo provate a confrontare il tab Network dei Developer Tools (cioè l'F12) del vostro browser preferito: la differenza tra il numero di file caricati dal progetto della nostra serie e quelli di questo progetto vale più di mille parole (ma non disperate, ci arriveremo a suo tempo);
  • Il bundling di Webpack viene gestito attraverso un middleware ASP.NET Core dedicato che si trova nel package NuGet SpaServices referenziato nel progetto. Tale middleware è caricato nella pipeline di ASP.NET Core solo in ambiente di sviluppo ed è per questo che è fondamentale impostare la variabile ASPNETCORE_ENVIRONMENT come prima descritto. In caso contrario le vostre modifiche ai file presenti in ClientApp non sarebbero prese in considerazione da Webpack e i file in wwwroot rimarrebbero quelli originali
    ;
  • In teoria i JavaScriptServices supportano l'Hot Module Replacement ma in pratica, come si vede nello screenshot qui sopra, questa opzione è disabilitata nel template di Aurelia per via di un problema con il plugin che consente di fare funzionare il framework con Webpack. Intanto che il problema viene risolto cerchiamo di capire cosa ci stiamo perdendo: abbiamo detto in precedenza che, quando facciamo una modifica ai nostri file di progetto (html o js/ts), Webpack si occupa di aggiornare i file presenti in wwwroot che saranno poi quelli serviti al client. In un'applicazione SPA questo non è sufficiente per "vedere" la modifica nel browser. La coppia View/ViewModel è stata infatti già richiesta al server e da quel momento in poi il framework SPA la riutilizza per ridurre la necessità di effettuare richiesta al server. Per ottenere la vista modificata dobbiamo aggiornare l'intera pagina (in genere con F5, presupponendo di avere la cache del browser disabilitata) ma questo vuol dire ovviamente perdere completamente il contesto di esecuzione del nostro test, ritrovandosi con una nuova istanza applicativa. Ecco l'HMR vuole risolvere appunto questo problema, iniettando html e js aggiornati nella SPA senza perdere il contesto di esecuzione corrente.

Happy coding!

«February»
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
2627281234
567891011