Il blog di Sandro Rizzetto

Esperienze d'uso con MudBlazor e Blazor WebAssembly

 

Problema: quando sul divano faccio "zapping" tra migliaia di thumbnail di film sulle varie piattaforme di streaming, certe volte mi viene il dubbio se l'abbiamo già visto o no. La UI/UX della pagina #FilmVisti del mio sito non proprio ottimizzato per lo smartphone, non rende l'esperienza d'uso delle ricerca facile e veloce.

Mission: sviluppare in Blazor WASM + MinimalApi (tutto .net 6) una semplice e pulita SPA fruibile da desktop/tablet/phone

Svolgimento: utilizzare (e imparare da zero) una libreria free (MudBlazor) che promette di dimenticarsi di CSS, JS e che offre molti componenti già pronti  sia per un front-end che per una admin app.

In poche ore (con il solito problema del "il 90% del sw era pronto nel 10% del tempo impiegato, ma per il restante 10% ce ne è voluto...") è quindi nato

myReviews.rizzetto.com

MudBlazor

Era un po' di tempo che la seguivo su Twitter ma ne aspettavo l'uscita della sua versione 6 che fosse totalmente compatibile con l'omologa di .net e che applicasse i suoi paradigmi (es. nei template niente startup.cs, ecc.). Quando poche settimane fa è uscita, mi ci sono subito buttato dentro e devo dire che mi sta dando molte soddisfazioni.

Nata come Component Library aderente agli stili del Material Design, si è evoluta nel tempo grazie all'impegno della community (ricordiamo che è free, open-source e con i sorgenti disponibili su Github) diventando quasi un framework e fornendo decine di componenti di UI da classici come quelli di Forms/Input fino ai più evoluti che sfoceranno in una DataGrid attualmente in fase experimental.

La lista dei componenti è veramente fornita ma quello che la distingue da altre che ho provato (MatBlazor, Blazorise) è il concetto di Theming che sta alla base di tutto l'impianto del layout. Ne viene fornito uno di Default (anzi due, perché con una sola proprietà boolean possiamo switchare tra Dark e Light come ho fatto anche io nella mia app) ma è molto facile fare tuning su quello di default creandosene uno custom e cambiando solo quello che ci serve. Nel file MainLayout.razor andremo infatti a fare una cosa del genere:

<MudThemeProvider Theme="RizTheme" />

@code
{
MudTheme RizTheme = new MudTheme()
	{
	Palette = new Palette()
	{
		Primary = Colors.Blue.Darken2,
		Secondary = Colors.Indigo.Darken3,
		AppbarBackground = Colors.Blue.Darken2
	},
	Typography = new Typography()
	{
		H6 = new H6()
		{ LineHeight = 1.2 }
	}
	};
}

Come si vede ho solo cambiato i due colori Primary e Secondary, il background della barra di header e la line-height del tag H6. E come l'ho fatto? In C#!!

Ecco infatti la grande novità, tutto lo styling non lo si fa mai da CSS ma si può fare tutto con le proprietà dei vari componenti, con le classi già fornite di standard e se non piacciono, facendo tuning dei vari parametri del theme (che sono moltissimi!)

Se siete curiosi e andate a vedere il mio css vedrete infatti che non ho dovuto definire nessuno stile o fare override !important(i) di stili già definiti. Quelle poche classi che ci sono, servono solo allo splash screen iniziale con il mio logo rotante e ad una pagina statica che viene fuori ai giapponesi della II guerra mondiale sull'isola sperduta che usano ancora browser non supportati da wasm (IE11, Edge vecchio, ecc.)

Tolto di mezzo il knowledge CSS, possiamo fare lo stesso con il javascript, visto che il comportamento dinamico di apertura chiusura (es. di un Drawer, una sidebar, ecc.) sono tutti compresi e cablati nei componenti. E Bootstrap? Anche quello inutile, anzi se già conosciamo il famoso framework di UI, all'inizio si fa un po' di fatica in quanto, è vero che molti concetti (come i breakpoints o le classi per lo spacing) sono uguali, ma i valori impiegati sono diversi. I margin e i padding ad esempio sono 16 e non 5 e sono tutti a step di 4px (quindi ad es. class="mb-5 pr-10" setta un margin-bottom di 20px e un padding right di 40). Le stesse classi per le griglie responsive (da xs a xx -e non xxl!-) hanno valori diversi da quelli di BS e se devo essere sincero sono molto più aderenti alla realtà odierna. Questo essersi allontanati dallo standard BS purtroppo ha anche degli svantaggi perché magari ogni tanto un componente di terze parti o uno snippet fatto con BS5 può essere utile, ma è proprio vietato includere il file bootstrap.css pena il mancato e  completo funzionamento di tutto.

Infine, teoricamente, potremmo fare a meno anche di conoscere l'html in quanto si può fare moltissimo solo con i componenti stessi senza usare nessun tag standard. La single page della mia applicazione infatti non ha NEANCHE un tag ma solo <MudQualcosa> o <RizQualcosa> che aggregano altri <Mud...>  (non finirò mai di lodare la bellezza di Blazor per come riesca a far creare pagine "pulite" e compatte col suo modelli di nested component).

Tutto rose e fiori quindi? Spesso mi chiedo se sia la strada giusta basare tutto sull'utilizzo di componenti esterni. Se la maggior parte dei componenti è al 100% utile e fa risparmiare un sacco di tempo, scrivere

<MudContainer>
        <MudText Typo="Typo.h1">My Title</MudText>
        <MudText Typo="Typo.body1">Lorem ipsum</MudText>
        <MudDivider />
</MudContainer>

sappiamo essere assolutamente uguale a 

<div class="container">
    <h1>My Title</h1>
    <p>Lorem Ipsum</p>
    <hr />
</div>

È chiaro che se un giorno decidessi di abbandonare questa libreria il front-end infarcito di <Mud> anche per semplici tag andrebbe praticamente riscritto. Solo che quando ci si prende un po' la mano e si conoscono i componenti è veramente difficile non utilizzarli, ed inoltre si ha sempre la certezza che lo stile e il layout sono sempre conformi e coerenti al Theme impostato dal ThemeProvider. Quindi mettendo da parte i miei dubbi iniziali, almeno per questa mini-SPA e per un'altra applicazione un po' più grossa che sto scrivendo con MudBlazor, mi sono imposto di utilizzarlo al 100%.

Documentazione, Supporto e TryMe!

Pochi giorni fa è uscita la nuova versione del front-end del sito di Documentazione della libreria e devo dire che è veramente ben fatto. Ogni componente ha una pagina di spiegazioni ed esempi e una di "reference" presumo auto-generata. I concetti principali sono ben spiegati così come sono riportati tutti i valori delle costanti, dei default, ecc.

Molto utile, anzi stra-utile, è il "support" offerto dal creatore originale Gardenroben (a cui poi si è aggiunto un secondo, Heron) tramite la piattaforma Discord. Se devo essere sincero trovo un po' ridondanti alcuni channels (se uno ha un dubbio non sa mai se scriverlo in #chat, #help, #development, o altri), ma la quantità di persone che vi gravitano e la disponibilità di autori e contributors è encomiabile. Oggi (domenica) alle 8.50 di mattina ho buttato lì un dubbio sull'utilizzo di un componente e in 3 minuti l'autore mi ha risposto. Certo, non è un support istituzionalizzato come quello di una libreria a pagamento (amo quello di DevExpress ma ha anche dei costi annui non indifferenti), ma tra Discord, le discussion su GitHub e il fatto di poter guardare i sorgenti, c'è una buona possibilità di risolvere in fretta i propri problemi (oppure di appurare che c'è un bug :-( )

Infine, chicca notevolissima e senza uguali, la piattaforma TryMudBlazor, un autentico playground dove scrivere del codice, compilarlo ed eseguirlo e salvare lo snippet per magari farlo esaminare e correggere a qualche anima pia su Discord. Veramente "innovativo" (ne avevo visti solo per Css e Js) e comodo.

Insomma, non so se la adotterei a colpo sicuro per un grosso progetto enterprise dove il fattore "support" e quick bug-fixing delle grosse software houses come DevExpress, Telerik, Syncfusion, in teoria dovrebbe essere assicurato; ma per progetti personali, no-profit o anche commerciali non proprio mission-critical non avrei dubbi a consigliarla.

Blazor WebAssembly

Un paio di considerazioni su questo "flavour" che ho usato molto meno spesso (anzi direi che per qualcosa che non fosse una demo è la prima volta) del fratello Server. Non mi ha convinto :-)

Gli svantaggi/difetti

  • necessità di sviluppare le API che aumentano di parecchio i tempi di sviluppo
  • efficacia del debugging ancora inferiore alla versione server
  • minore affidabilità della funzionalità di hot-reload di VS2022 (non mantiene lo stato al contrario della versione server)
  • tempi di caricamento non indifferenti all'avvio dell'applicazione (pensavo non fosse una issue con le linee di adesso, ma dopo 3 volte che vedi girare lo spinner, ti gira qualcos'altro)

sono infatti a mio avviso ancora superiori ai pregi, almeno fino a quando nel Q2 non uscirà la RTM di MAUI e potremmo tastare con mano quanto effettivamente sia funzionale la portabilità nel mondo desktop (webview) e mobile.

Infinite Scroll

Parlando del progetto relativo al mio sito mtb.rizzetto.com, spiegavo come avevo ottenuto questa funzionalità usando la libreria htmx. In questo caso devo invece dare i credits a questo developer per avermi indirizzato sulla giusta strada sull'uso dell'oggetto window.Observer (cosa che hanno fatto anche altri vedendo i pochi esempi sul web). Teoricamente la strada "giusta" da seguire dovrebbe essere quella di usare il componente Virtualize proprio di Blazor; mi riservo di approfondire la questione nel prossimo progetto.

Parametri facoltativi nelle Minimal Api

Volendo creare un endpoint che gestisse la paginazione con due parametri passati via querystring, ma non obbligatori, non riuscivo a capire come fare a "decorarli not-required". La risposta è semplice quanto banale; basta renderli nullable. Nell'esempio qui sotto si vede infatti come i due int? non vengano marcati obbligatori da Swagger

Personalizzare il messaggio di attesa del caricamento app

Se avete avuto la compiacenza di aprire la mia piccola webapp, avrete notato (a meno che non abbiate una linea a ten-gigabit!) la personalizzazione al posto dell'antiestetico messaggio Loading scritto in times new roman. La cosa è banale da farsi, basta infatti nel file wwwroot\index.html cercare <div id="app"></div> e al suo interno mettere quello che si vuole. Se poi ci mettete di più a centrare orizzontalmente e verticalmente una scritta che non a fare tutto il progetto, siete in buona compagnia! ;-)

 

Aggiungi Commento

Copyright © 1997-2022 Sandro Rizzetto | All Rights Reserved | Riproduzione delle fotografie vietata | Powered by me