In questo ultimo periodo anche io ho subito il fascino di Blazor, il nuovo sistema framework per scrivere web-app in salsa M$.
Sin dal primo momento che mi sono approcciato all’argomento mi sono reso conto che questo l’argomento è veramente una gran figata: so di non essere molto professionale ad usare un termine del genere, ma direi che rende l’idea di quello che umilmente ne penso.
Di questo nuovo framework mi è da subito piaciuto da subito l’approccio alla programmazione proposto, non certo elegante, ma efficace e comprensibile.
Eppoi questo stile di programmazione, che miscela HTML con C#, mi ricorda i tempi gloriosi di asp/vbscript: boh, non so, forse è una mia idea balorda, ma alcuni punti di incontro tra questi due mondi così lontani nel tempo francamente li vedo.
In modo meno prosaico posso continuare dicendo che la cosa che più mi ha convinto di Blazor è la possibilità di scrivere web-app dotate di una robusta logica di funzionamento lato client (Angular-style per capirsi) senza dover utilizzare nulla che ha a che fare con javascript o typescript.
Per inciso: contro javascript non ho nulla, semplicemente è un linguaggio che non mi è mai piaciuto molto. ….tra di noi non c’è mai stata la scintilla, ecco…… Anche il suo cugino typescript non mi ha mai convinto eccessivamente.
Inoltre un’altro motivo a supporto di questa “mancata simpatia è il seguente”. Sino all’arrivo di Blazor per implementare una moderna web-app occorreva scrivere il codice costitutivo utilizzando C# (o similari) per implementare la logica lato server, e quindi utilizzare forzatamente javascript o typescript per implementare la logica lato client.
Questo continuo switch “della testa” tra due linguaggi mi ha sempre messo in difficoltà: sarà anche l’età ?!?!?!
Comunque sia con Blazor possiamo dimenticarci (..o quasi) di usare javascript/typescript per scrivere codice che implementa logica lato client, e usare sempre e comunque C#, il che secondo me non è cosa da poco.
In questa serie cercherò di dare il mio modestissimo contributo sull’argomento. Per iniziare Vi esporrò cosa ho capito io dell’argomento: successivamente, siccome la tecnologia è perfettamente utilizzabile nel mondo mobile-app, presenterò alcuni utilizzi pratici nell’ambito di progetti con il mio amato Xamarin.
Blazor…. In continuo divenire
Prima di continuare occorre dire che il mondo di Blazor attualmente è in “continuo divenire”, essendo in pratica ancora in sviluppo: per questo quello che Vi esporrò qui potrebbe non essere più valido nel momento in cui leggerete questo scritto.
In questi ultimi mesi i cambiamenti al framework sono stati molti e nelle varie revisioni sono stati introdotti anche svariati breaking-change: in ogni caso con un pò di pazienza e grazie a san-google sarà sempre possibile riportare il progetto bizzoso presentato qui e che non ne vuole sapere di compilare con una successiva futura versione del framework a più miti consigli.
Per gli stessi motivi per approcciarsi al fantastico mondo di Blazor consiglio di adottare Visual Studio 2019 Preview “ultimo grido”, con applicati ad esso tutti gli aggiornamenti.
Mi permetto di evidenziare nuovamente che il VS 2019 deve essere nella versione Preview, e non la versione stabile, altrimenti non funziona una cippa !
Blazor è ancora in versione beta, e pertanto il suo utilizzo è possibile solo con VS 2019 Preview.
Per completezza riporto che si narra che si possa ottenere un risultato simile anche con VS 2019 Stabile, azionando qualche flag oscuro e “carbonaro”, ma per evitare confusione e problemi (visto che per me VS 2019 stabile è uno strumento di lavoro che uso giornalmente) ho preferito usare questa strada (tra l’altro consigliata anche dai sacri testi M$), che mi permetto di consigliare anche a Voi.
Oss.: Sulla stessa macchina possono coesistere, senza che si bisticcino in alcun modo tutte le versioni di VS2019, in particolare modo VS 2019 Preview e la versione stabile.
Fatto questo occorre installare la versione .Net Core 3, che al momento della scrittura di questo post è in preview: utilizzate senza indugio l’ultima versione (al momento in cui scrivo la preview 8)
Quanto sopra non è ancora sufficiente purtroppo: mancano ancora i maledetti template che nelle vecchie versioni di Blazor mi hanno fatto dannare non poco. Per farli apparire occorre dare il seguente comando da una command line.
dotnet new –install “Microsoft.AspNetCore.Blazor.Templates”
In ogni caso date un’occhio in linkografia a “Get started with ASP.NET Core Blazor” che dovrebbe riportare eventuali variazioni alla procedura esposta sopra.
Qualche concetto sulle web-app moderne
A meno che non abbiate nascosto la testa e il monitor del pc sotto la sabbia in questi ultimi anni, lo sviluppo delle applicazioni web è molto cambiato.
Per affrontare Blazor (che al momento è la punta dell’iceberg di questo mondo) occorre avere ben presente l’ambito di utilizzo delle ultime tecnologie utilizzate, nonché i concetti che sottendono a queste.
Solo in questo modo si comprende dove e come si pone questo framework, e quali problematiche intende affrontare.
Per questo motivo mi preme scriverne qualcosa nel seguito: l’esposizione è volutamente pressapochista (daltronde visto il nome del blog non poteva essere altrimenti…..) e in alcune parti molto esemplificativa.
In ogni caso l’intento è quello di fornire un crash-course per poter capire di cosa si parla.
Web-App old style: round trip model (anche chiamato MPA Multi Page Application)
Sino a non molto tempo fa i siti erano costruiti esclusivamente seguendo il pattern denominato round-trip.
Con questo pattern ad ogni interazione che l’utilizzatore ha con la pagina web (click su un link, un bottone, etc etc), e qualora si renda renda necessario modificare il contenuto presentato, questo provocherà un evento che informerà il browser circa la necessità di contattare il web server per ottenere una completamente nuova pagina HTML aggiornata. Questa nuova pagina ottenuta verrà quindi completamente e interamente sostituita a quella visualizzata: così il nuovo contenuto viene presentato all’utilizzatore.
Con questa modalità il browser è delegato semplicemente a ricevere le pagine web Html e renderle visibile all’utilizzatore, nonché a interrogare il web server per farsi restituire eventualmente i nuovi contenuti.
L’intera logica di funzionamento della web-app è tutta completamente eseguita lato web-server: anche il codice che si occupa di creare le nuove pagina è completamente conservato lato server, e al client-browser arrivano solo le pagine Html create.
I drawback di un modello come questo possono essere riassunti nei seguenti punti.
- La parte server è delegata a elaborare le richieste di tutti gli utilizzatori: questo introduce criticità circa il suo dimensionamento, che deve essere tale da poter servire tutti gli utilizzatori.
- Anche a fronte di una piccola modifica della pagina questa deve essere completamente ricaricata dal web server: questo occorre anche a fronte di modifiche che coinvolgono una piccola parte della pagina stessa. Questo introduce ovviamente latenze nell’interazione della UI nonché utilizzo di connettività.
Il pattern MPA è ancora perfettamente in uso, ma un approccio più evoluto, che permette di ovviare alle problematiche esposte sopra, è il Single-Page.
Single-Page web-app (SPA Single Page Application per gli amici….)
Con questo pattern quando l’utilizzatore si connette per la prima volta a un server web riceve un documento HTML iniziale, che quindi viene visualizzato dal browser.
Insieme al codice HTML costitutivo della pagina viene anche restituito anche del codice, che viene posto in esecuzione all’interno del browser.
Questa volta a seguito dell’interazione dell’utilizzatore possono occorrere le seguenti cose.
- Il codice che equipaggia la pagina HTML intercetta l’evento ed esegue direttamente la modifica della pagina richiesta dalla logica di funzionamento senza coinvolgere in alcun modo il web-server.
- Il codice che equipaggia la pagina HTML intercetta l’evento e contatta il web-server per poter aggiornare solo la parte di pagina interessata alla modifica.
Ovviamente tutto questo è possibile grazie al codice che equipaggia la pagina HTML, e che è in esecuzione nel browser: questo rappresenta la logica di funzionamento client-side e le pagina che presentano tale caratteristica si chiamano appunto Sinlge-Page web-app.
Il linguaggio “principe” per implementare il codice client-side è javascript e, solo recentemente, è stato introdotto typescript (che comunque è legato a doppio, se non triplo, filo sempre a javascript).
L’adozione di linguaggi alternativi al mondo javascript è ovviamente ostacolato dal fatto che praticamente tutti i browser in uso supportano nativamente questa tecnologia.
Per adottare un sistema o linguaggio alternativo occorre generalmente prima far installare qualche plug-in dedicato per adattare il browser stesso, cosa non sempre agevole e facile da gestire.
Occorre osservare che web-app reali nella pratica sono costituite da un misto di SPA ed MPA: infatti per alcune parti è meglio usare un approccio SPA, mentre per altre della stessa web-app è possibile trovare più efficace affidarsi a MPA.
Comunque sia da qualche anno è possibile utilizzare nativamente una nuova tecnologia: WebAssembly (o WASM, se si vuole usare un termine più figo).
WebAssembly
Penso sia importante evidenziare come javascript sia un linguaggio interpretato, e che l’interprete è incluso del browser che si sta utilizzando.
Questo si traduce nella pratica con alcune penalità nell’ambito delle perfomance: come noto, e generalizzando parecchio, i linguaggi interpretati sono sempre più lenti di quelli compilati.
Questo però non ha fermato javascript dal diventare in pratica l’unico linguaggio da utilizzare per scrivere codice client-side: tra l’altro le macchine sono sempre più veloci, e a meno di applicazioni molto particolari generalmente le perfomance proposte sono sempre più che sufficienti.
Inoltre come detto l’interprete javascript è presente in tutti i browser, e quindi giocoforza ha sempre rappresentato la scelta più efficace.
Comunque qualche anno fa è entrato nell’arena il WebAssembly.
Si tratta di un linguaggio di programmazione a basso livello (qualcosa di simile ad assembly, per capirsi) che si propone come sostituto di javascript.
Con WASM è possibile utilizzare dei linguaggi di alto livello (JavaScript, C, C++, Rust, Python, etc etc) per scrivere logiche di funzionamento paragonabili a quelle proposte da javascript, e quindi compilarli e ottenere bytecode di basso livello, appunto WebAssembly, che può essere eseguito direttamente dal browser.
In altri termini il WebAssembly non è stato pensato principalmente per essere utilizzato direttamente per scrivere codice client-side, bensì come target di compilazione per linguaggi di più alto livello, in modo da avere un formato più compatto e veloce da eseguire.
I vantaggio di usare WASM rispetto a javascript possono essere riassunti nei seguenti punti.
- Perfomance: il codice WASM viene eseguito con prestazioni molto vicine a quello di codice nativo.
- Dimensioni file: le dimensioni dei file di byte code sono molto inferiori rispetto ad analoghi programmi scritti in javascript.
- Migliore utilizzo memoria: WASM è un linguaggio tipizzato, e questo permette un più minuzioso ed efficace utilizzo della memoria.
- Maggiore scelta di linguaggi di programmazione: è possibile usare una serie di linguaggi di programmazione diversi da javascript per scrivere software client-side
Sembrerebbe che non vi sia più ragione per usare ancora javascript progetti relativi a web-app: purtroppo le cose non sono così semplici.
Per iniziare il grosso scoglio è che WASM è abbastanza recente, e quindi non tutti i browser sono in grado di comprendere questo nuovo formato.
Per meglio specificare i contorni del problema occorre dire che tutti i browser maggiori (compresi anche la loro versione mobile) oramai da una paio di anni supportano questo nuovo standard: quindi è possibile affermare che il problema della compatibilità è abbastanza limitato a casi limite.
Inoltre nei casi in cui il browser non supporti webassembly è possibile l’adozione di polyfills dedicati (vedere dopo).
L’altro problema è che ad oggi WASM non è ancora in grado di accedere completamente al DOM della pagina HTML: questo si traduce con l’impossibilità di cambiare completamente ogni contenuto di una pagina, cosa per esempio possibile con la sua controparte javascript.
Anche su questo punto occorre dire qualcosa: questa limitazione, ad oggi ancora parzialmente presente, potrebbe essere superata a breve nei prossimi sviluppi di WASM.
Inoltre è stato previsto sin dalla sia nascita che WASM e javascript possano non solo coesistere pacificamente, ma anche che potessero interagire tra loro senza problema alcuno.
Per questo è facilmente possibile (e in pratica si fa proprio così) poter richiamare da WASM frammenti di codice javascript delegati esclusivamente a interagire con alcune parti del DOM della pagina web preclusi a webassembly.
Ovvia anche la possibilità, grazie a questa possibilità, di riutilizzare codice legacy javascript in progetti che inizino ad utilizzare WASM.
Polyfills
Può capitare di imbattersi in questo termine quando si studia WASM e Blazor, ma non solo, e pertanto per completezza ne scrivo qualcosa.
Polyfills è un termine generico che identifica codice generalmente javascript che permette di usare API del browser senza che questo le supporti nativamente.
Un esempio su tutti: internet explorer NON supporta webassemby, e pertanto non potrebbe eseguire per esempio codice Blazor o comunque scritto in WASM.
Grazie all’adozione di polyfills dedicate (esiste ed è molto utilizzata quella per IE11) è possibile aggirare questo problema.
Nella pratica basta includerle nella web-app ed è possibile eseguire codice webassembly anche su browser che non lo supportano nativamente.
Oss.: Edge, al contrario di IE, supporta nativamente WASM.
Che ci azzecca Blazor con WebAssembly ?
Come abbiamo visto il WASM apre alla possibilità di utilizzare tutta una serie di linguaggi alternativi a javascript per scrivere software client-side che quindi è in esecuzione nel browser: quindi perché non anche C# ??
Quindi ecco il focus: Blazor è un framework che permette di scrivere web-app con l’ausilio di codice C# da poter eseguire lato client (cioè all’interno del browser).
Per poter implementare questa magia si usa webassembly.
Detto questo si potrebbe pensare che il codice per lato client scritto in C# è compilato direttamente in WASM: purtroppo le cose in realtà sono leggermente più complicate (non troppo….), e sarà oggetto del prossimo post.
Inoltre per complicare le cose è possibile utilizzare Blazor senza uso di WebAssembly, ma questo è un caso particolare che esporrò nei prossimi post.
In ogni caso NON esisterebbe Blazor, e quindi la possibilità di scrivere codice da mandare in esecuzione lato client sul browser in C#, senza WASM.
Progressive Web App (o anche PWA)
E’ possibile pensare alle progressive web app come a una evoluzione delle web-app dedicate al mondo mobile, e quindi ottimizzate per questa piattaforma.
Si tratta di web-app che in pratica si presentano come una app nativa per mobile: in altri termini la user interface nell’aspetto è molto vicina a una app mobile nativa.
Inoltre le PWA sono, tra le altre cose, in grado di funzionare offline e inoltre sono installabili proprio come fossero app native (in modo tale da poterle aggiungere, per esempio, alla schermata home senza necessità di ricordare l’indirizzo del sito o salvarlo nei preferiti del browser).
La cosa inizialmente era in questi termini, ma con il passare del tempo la tecnologia è andata ben oltre, e ora tali applicazioni sono ampiamente utilizzate e disponibili anche per desktop.
Per la loro natura fanno largo uso di javascript e ora di webassembly: la maggior parte delle volte si tratta di SPA.
Però e da ricordare sempre: una web-app di tipo SPA non è detto che sia PWA, ma quasi sempre una PWA è una SPA.
Nel prossimo esporrò come creare una PWA usando Blazor.
Linkografia
Get started with ASP.NET Core Blazor
Download .NET Core 3.0
Blazor.Polyfill – Il polyfills per utilizzare WASM in IE 11