Come avete potuto leggere negli articoli precedenti, il funzionamento di base di Blazor Server è completamente diverso dalla versione WebAssembly, pur condividendo il modo in cui vengono realizzati i componenti e strutturate le pagine. Come facciamo a scegliere quale dei due fa al caso nostro? O, meglio, quale dei due si adatta meglio ai nostri requisiti?

Blazor WebAssembly vs Blazor Server

Ad oggi Blazor WebAssembly è in preview, quindi non è possibile utilizzarlo in produzione. Questo è un problema che sarà risolto entro Maggio di quest’anno, mese in cui è previsto il rilascio in RTM di questa versione del framework. Inoltre, per poter funzionare, la versione WASM richiede il supporto del browser, che ad oggi è garantita su Edge, Firefox, Safari, Opera e i principali browser mobile. Possiamo verificare il supporto qui.

Supporto WebAssembly sui browser

D’altro canto, l’utilizzo di SignalR in Blazor Server, su numeri veramente importanti, può creare un limite di scalabilità, che va gestito opportunamente. Il problema nasce perchè SignalR richiede che sia lo stesso processo server a gestire una specifica connessione, quindi la scalabilità di SignalR è legata a quella della singola macchina. Se aggiungiamo macchine per gestire più utenti, dobbiamo assicurarci che le richieste dei singoli utenti arrivino alla stessa macchina da cui la connessione è iniziata, cosa che può essere gestita, per esempio, con i sistemi di affinity dei Load Balancer.

Tutto questo è necessario perchè la negoziazione di SignalR potrebbe non scegliere WebSocket come trasporto, cosa che volendo è possibile forzare utilizzando il valore true per l’impostazione SkipNegotiation, ma ci escluderebbe i client che non supportano WebSocket.

SignalR Service vs Redis Backplane

Se ospitiamo la vostra applicazione su Azure, esiste un apposito servizio chiamato Azure SignalR Service che risolve il problema per noi. Se siete on-premise o non volete usare SignalR Service è possibile utilizzare Redis, il famoso key-value store spesso usato per il caching dei dati, come Backplane: si tratta di sfruttare Redis come Hub per la gestione delle connessioni, inviandogli tutte le informazioni sui client collegati, e il dispatching dei messaggi, mandandogli i messaggi da inviare ai client giusti. Possiamo trovare maggiorni informazioni qui.

Un’altra differenza tra i due è il framework .NET utilizzato: nel caso di Blazor Server abbiamo a disposizione tutto il framework .NET Core, mentre con Blazor WebAssembly utilizziamo Mono, grazie alla compatibilità garantita dalle Standard Libraries. Viste le limitazioni che abbiamo nel browser in termini di sicurezza, anche questo non è un problema discriminante, ma va comunque preso in considerazione.

Analizzati i problemi risolvibili, vediamo adesso le caratteristiche che separano nettamente le due versioni del framework.

On-line vs off-line

Una delle principali caratteristiche di una Single Page Application è quella di elaborare sul client l’interfaccia utente, cosa che potrebbe essere fatta senza nessun supporto da parte del server. In Blazor Server questa operazione non è possibile, perchè l’elaborazione avviene sul server e richiede una connessione stabile per il funzionamento.

In Blazor WebAssembly possiamo invece supportare gli scenari off-line, lavorare cioè in assenza di connessione. Il framework ci fornisce la possibilità di lavorare sul client e interrogare il server solo quando abbiamo bisogno di recuperare o inviare dati, utilizzando l’HTTP Client. Supportare veramente uno scenario off-line però è una cosa più complessa, richiede la capacità di rilevare la presenza o meno della connessione e lavorare sui dati anche in assenza di essa, essenso capaci poi di riconciliarli una volta che la connessione torna disponibile. Essere in grado di lavorare off-line ci abilita anche alla realizzazione di una Progressive Web App (PWA), cosa da non sottovalutare.

Quindi nei casi in cui non abbiamo necessità di collegarci al server o vi ci collegiamo saltuariamente, possiamo sfruttare Blazor WebAssembly senza costi aggiuntivi. In Blazor Server questa cosa non è proprio possibile.

C’è però da valutare un altro aspetto: i dati sensibili. Premesso che dovremmo sempre evitare con tutte le vostre forze di gestire dati sensibili nel presentation layer delle nostre applicazioni, avere il codice sul client ci espone a rendere accessibili tali informazioni. Utilizzando Blazor Server tutto resta sul server e eventuali dati sensibili, come dei token di accesso a servizi terzi come quelli di Azure, non vengono proprio inviati al client.

Dimensioni e latenza

La dimensione dei dati da scaricare in Blazor WebAssembly, al primo download, è molto più grande di quella necessaria per Blazor Server. Questo perchè nel primo caso scarichiamo nel browser tutte le librerie, il framework Mono per Webassembly e tutti i file di supporto; nel secondo caso invece tiriamo giù solo HTML, CSS e JavaScript, mentre il resto viene fato lato server. In una applicazione enterprise attendere qualche secondo per il primo download non è un grosso problema, mentre se decidessimo di usare Blazor per un sito o una applicazione pubblica, il primo download può impattare sull’esperienza utente.

Strettamente collegata alla questione on-line/off-line c’è anche la questione latenza: dover richiamare il server per ogni operazione di aggiornamento dell’interfaccia può impattare sulle prestazioni e sull’esperienza utente in caso di connessione non stabile.

Il problema della dimensione è uno degli aspetti su cui il team di Microsoft sta lavorando prima del rilascio in RTM di Blazor WebAssembly, insieme all’esperienza di debug…

Esperienza di debug

Con Blazor Server stiamo lavorando con una vera e propria applicazione ASP.NET Core, il tutto avviene sul server e quindi basta mettere un punto di interruzione nel codice per eseguire le fasi di debug della nostra applicazione. Su questo i tool Microsoft hanno pochi rivali sul mercato, e sia che usiate Visual Studio Code che Visual Studio, l’esperienza di debug sarà estramemente confortante.

Su questo Blazor WebAssembly non riesce, ad oggi, a tenere il passo. Il debug avviene nel browser, in un tab separato, abilitando opportunamente il tutto con dei comandi specifici. Il primo passo è avviare l’applicazione con la configurazione di Debug: dotnet run --configuration Debug. Apriamo il browser e tenendo il focus sulla nostra applicazione, utilizziamo la combinazione di tasti Shift+Alt+D se siamo su Windows o Shift+Cmd+D se siamo su MAC. Vi si aprirà un nuovo tab in cui troverete le istruzioni su come avviare il browser (Chrome o Edge) in modalità di Debug:

Comandi per il Debug di Blazor WebAssembly

Copiate il comando proposto nel tab, chiudete tutte le istanze di browser aperte, incollate nel terminale il comando copiato e lanciatelo: sarà aperto il browser scelto in cui potete aprire l’applicazione e rieseguire la seguenza di tasti che aprirà il tab per il debug:

Debug di Blazor WebAssembly

Possiamo impostare e rimuovere i punti di interruzione, usare F10e F8per muoverci nel codice e nella sezione variabili locali e stack per guardare il valore delle variabili o lo stack delle chiamate. Purtroppo però al momento possiamo vedere solo le variabili di tipo int, string o bool e solo nella sezione variabili locali, quindi non possiamo usare il mouse per sovrapporci alla variabile interessata e vederne nel tooltip il valore corrente. Non possiamo valutare le espressioni nella console come facciamo con la finestra immediata di Visual Studio e muoverci tra le chiamate asincrone.

Considerate che uno dei principali problemi in questo caso e il mapping tra il codice sorgente e il codice eseguito, che nel mondo JavaScript è risolto anche in casi di transpilazione (TypeScript) e minificazione con l’uso dei file .map, in questo caso non avendo un mapping diretto tra C# e WASM (come abbiamo detto nel precedente articolo, il codice C# non viene compilato direttamente in WASM), la cosa diventa più complessa.

Sì, è un po’ disarmante, ma il team di Microsoft ci sta lavorando duramente per arrivare a una esperienza di debug moderna prima del rilascio della RTM.

Conclusioni

Quale scegliere quindi? La risposta è: dipende! Non dovrebbe mai essere la tecnologia a guidare la scelta e inventare poi requisiti per giustificarla: scegliete in base ai requisiti. Date però importanza anche ai requisiti non funzionali, che spesso e volentieri possono fare la differenza tra una applicazione di successo e una che non viene utilizzata.

Finisce qui la nostra introduzione al framework, dai prossimi articoli entreremo nel dettaglio di come realizzare una Single Page Application con Blazor, con un approccio estremamente pratico e introducendo dei pattern che possono aiutarci a manutenere meglio il nostro codice e a gestire le situazioni ibride che spesso sono parte integrante della vita reale.