Articoli

Blazor WebAssembly

da

Dopo Blazor Server vediamo come funziona la versione WebAssembly, rilasciato per la prima volta nel Maggio 2020.

WebAssembly: non di solo JavaScript vive il browser

Lo sviluppo web ci ha abituato a pensare che l’unico modo di eseguire codice nel browser sia JavaScript, ed è stato così fino all’arrivo della specifica WebAssembly e della sua adozione nei principali browser moderni.

Il primo annuncio fu nel 2015, ma abbiamo dovuto attendere fino al 2017 per una prima preview. Nel Febbraio 2018 il WebAssembly Working Group, di cui Microsoft è parte attiva insieme a MozillaGoogle e Apple, coordinati dal W3C (World Wide Web Consortium), ha pubblicato le bozze della parte Core della specifica, insieme a quelle di interoperabilità con JavaScript e Web API.

Ad altissimo livello, possiamo immaginare il browser come un contenitore in cui possiamo definire la nostra interfaccia utilizzando HTML e CSS, interagendo tramite JavaScript con le API del browser (DOM, WebSocket, File API, Web Storage, ecc.). JavaScript viene eseguito all’interno di un ambiente controllato, chiamato JavaScript Runtime, che fornisce un unico thread per ogni tab o dominio che viene visualizzato.

WebAssembly si piazza esattamente nello stesso runtime, condividendo quindi gioie e dolori di questo ambiente e la possibilità di interagire con JavaScript. Questo significa che WebAssembly ci permette di fare tutto quello che facciamo con JavaScript e, laddove ci serva integrare codice legacy o utilizzare librerie JavaScript già pronte, è possibile invocare una funzione JavaScript da un metodo C#. Sicuramente interessante anche la possibilità di fare il contrario, invocare cioè da JavaScript una funzione esposta da WebAssembly.

Da .NET a WASM: cosa c’è veramente sotto?

Prima che si faccia confusione cerchiamo di capire davvero come funziona Blazor WebAssembly.

Lo standard WebAssembly, detto anche WASM, fornisce un formato binario nato con lo scopo di eseguire nel browser codice ad una velocità simile a quella del codice nativo. E’ possibile generare questo codice a partire da linguaggi ad alto livello, come C++, ma al momento non esiste un compilatore da C# a WASM.

Blazor ci permette di eseguire nel browser codice IL (Intermediate Language), generato a partire da C#, grazie al porting del runtime di mono allo standard WASM. I file contenenti codice WebAssembly hanno estensione WASM, il runtime di mono compilato per WebAssembly aveva il nome mono.wasm, rinominato nell’ultima versione a dotnet.wasm.

Se ad esempio il nostro progetto si chiama MyBlazorApp, non ci sarà un MyBlazoApp.WASM, ma un MyBlazorApp.DLL, che potete facilmente ispezione con un inspector di codice IL, come l’estensione per Visual Studio Code ILSpy.

Dal template al browser

Passiamo alla pratica! Creiamo un progetto Blazor WebAssembly e chiamiamolo MyBlazorApp con il comando dotnet new blazorwasm -o MyBlazorApp.

In questo tipo di progetto è stata notevolmente semplificata la configurazione, eliminando la classe Startup.cs tipica dei progetti ASP.NET Core. Ha molto senso perché il compilato di una applicazione WebAssembly è un insieme di file statici, che possono essere distribuiti con un qualsiasi web server, senza nessun bisogno di .NET. Quello che vediamo nel file Program.cs è la configurazione del web server che servirà i file e la registrazione del componente principale.

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

await builder.Build().RunAsync();

Eseguendo il progetto con il comando dotnet run o con il classico F5 di Visual Studio, possiamo vedere il risultato all’indirizzo http://localhost:XXXX (dove XXXX è una porta random): lanciate il browser e aprite i tool per gli sviluppatori sulla sezione Network, per verificare cosa viene scaricato.

Sì, non ci sono errori, quelle che vedete sono delle DLL scaricate nel browser! Non lasciate venire alla mente ricordi molesti (non è Silverlight…), ma grazie a dotnet.wasm possiamo eseguire le librerie .NET standard del progetto, compreso il nostro MyBlazorApp.dll. Nel file blazor.boot.json trovate l’elenco degli assembly che devono essere caricati, utilizzato dallo script blazor.webassembly.js per inizializzare l’applicazione.

L’applicazione sta girando nel client, niente WebSocket e niente back-end. Se pulite la sezione Network e cliccate sul counter dell’applicazione, vedrete che nessuna chiamata al server viene fatta. Se invece vi spostate su Fetch data, potete vedere la chiamata HTTP per il recupero dei dati visualizzati nella tabella, ma il rendering dell’HTML viene fatto client-side.

Conclusioni

Per oggi ci fermiamo qui. In questo articolo abbiamo analizzato le peculiarità di Blazor WebAssembly, cercando di capire le principali differenze di funzionamento con Blazor Server. Nel prossimo articolo faremo un confronto tra i due, analizzando pro e contro di ogni versione e in quali contesti una delle due risponde meglio ai nostri requisiti.