Attualmente, uno dei più grandi limiti di Blazor WebAssembly è il dover caricare tutte le dipendenze DLL necessarie a poter utilizzare C# nel browser. Il progetto di default, al primo avvio, necessita il download di oltre 16 MB di dati quando viene eseguito in debug:

Dimensione download Blazor WebAssembly

È pur vero che in produzione la dimensione si riduce quasi del 50% ma rimane un limite non da poco se paragonato ad altri framework di frontend come ad esempio Angular. In questo articolo purtroppo non riusciamo a sopperire a questa lacuna ma si vuole rendere più user friendly il loading iniziale dando la percezione che l’applicativo si sta caricando e non è bloccato. Attualmente la schermata iniziale di loading è questa:

Loading di default

Una semplice scritta Loading… immersa in un mare di bianco. Quando siamo in debug e quindi il server è locahost riusciamo a malapena ad intravedere la schermata mostrata sopra, ma che succede se il server è remoto e la nostra connessione non è la più veloce possibile? Purtroppo, la staticità di quella schermata può portare l’utente a pensare che ci sia qualche problema e nel caso peggiore anche ad abbandonare la navigazione. Rendiamo la fase di loading più “animata”.

HTML

Per fare ciò è necessario modificare il file index.html che si trova dentro wwwroot:

File index.html Blazor WebAssembly

Nel file index.html, subito dopo il tag <body> troviamo il tag al cui interno c’è il testo “Loading”:

Modifica file index.html Blazor WebAssembly

Andiamo a sostituire “Loading…” con questo html:

<div class="loading-section">
    <h2>Welcome</h2>
    <div class="short-description" id="loadingText">Loading, please wait</div>
    <div class="loader mt-3">
        <div class="loader-dot dot1"></div>
        <div class="loader-dot dot2"></div>
        <div class="loader-dot dot3"></div>
    </div>
    <p>Un attimo di pazienza, il programma si sta caricando</p>
</div>

Mi raccomando non cancellate i tag <app> altrimenti Blazor non funzionerà.

JavaScript

A malincuore dobbiamo usare un minimo di JavaScript perché in questa fase non abbiamo a disposizione C#. Nelle ultime release di Blazor WebAssembly, le DLL necessarie vengono caricate attraverso la chiamata fetch quindi possiamo sovrascrivere il metodo JavaScript ed intercettare le richieste verso il server.

Prima del tag script <script src="_framework/blazor.webassembly.js"></script>, andiamo a ridefinire fetch utilizzando il codice seguente:

<script type="text/javascript">
    (function () {
        let total = 0;
        let loaded = 0;

        let standardFetch = fetch;
        fetch = function (url, options) {
            total++;
            var promise = standardFetch(url, options);
            promise.then((data) => {
                let element = document.getElementById("loadingText");
                if (typeof (element) != 'undefined' && element != null)
                {
                    loaded++;
                    let progress = Math.floor(((loaded / total) * 100));
                    let url = new URL(data.url);
                    element.innerHTML = progress + "% - <i>loaded " + url.pathname + "</i>";
                }
            });
            return promise;
        }
    })();
</script>

Chi ha un po’ di dimestichezza con JavaScript può notare che il codice non fa altro che contare le richieste effettuate e quelle che vengono terminate per aggiornare il testo presente nel tag identificato dall’identificativo “loadingText”, che si trova nel codice HTML inserito in precedenza. Tale testo mostrerà la percentuale di caricamento e il nome dell’ultimo file caricato.

CSS

Adesso dobbiamo rendere più bello questo loading. Per farlo ho aggiunto un file CSS che ho chiamato custom.css:

Custom CSS

Ovviamente dovete inserire in index.html il collegamento a questo nuovo file CSS:

<link href="css/custom.css" rel="stylesheet" />

Vi consiglio di inserirlo subito dopo il riferimento al file site.css che è quello di default. Al suo interno ho inserito questo:

.loading-section {
    text-align: center;
    height: 55vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    margin: 0 auto;
}

.loading-section h2 {
    color: #0366d6;
}

.loader-dot {
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background-color: #0366d6;
    display: inline-block;
    -webkit-animation: grow 2.1s infinite ease-in-out both;
    animation: grow 2.1s infinite ease-in-out both;
}

.loader-dot.dot1 {
    -webkit-animation-delay: -0.96s;
    animation-delay: -0.96s;
}

.loader-dot.dot2 {
    -webkit-animation-delay: -0.48s;
    animation-delay: -0.48s;
}

@-webkit-keyframes grow {
    0%, 80%, 100% {
        -webkit-transform: scale(0)
    }

    40% {
        -webkit-transform: scale(1.0)
    }
}

Ovviamente potete personalizzare sia l’HTML che il CSS come meglio preferite.

Nel mio caso il risultato ottenuto è questo: Loading in azione Loading in azione

Avvertenze

E’ importante sottolineare che sovrascrivere il metodo fetch dei default del browser comporta l’utilizzo di quello sovrascritto per tutto il tempo che la pagina è aperta quindi se fate utilizzo di tale metodo ricordatevi che non è quello originale.

Conclusioni

Sicuramente il problema della velocità di caricamento non è stato risolto dalle funzionalità descritte nell’articolo ma si rende più consapevole di ciò che sta succedendo l’utente che usufruisce dell’applicativo. Spero che quando Blazor WebAssembly uscirà dalla fase di preview ci sia un netto miglioramento (se non la soluzione definitiva) al problema.