Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 29 de septiembre de 2020
Blazor

Como sabemos, al acceder por primera vez a una aplicación Blazor WebAssembly, durante unos segundos aparecerá en el navegador el mensaje "Loading...", indicando que se están descargando los recursos necesarios para que funcione la aplicación.

Vimos también en su momento que este mensaje puede ser modificado a nuestro antojo para sustituirlo por algo más apropiado, como un espectacular spinner:

Mensaje de carga personalizado

Sin embargo, si el navegador desde el que estamos accediendo es un vetusto Internet Explorer u otro sin soporte para Blazor WebAssembly, el mensaje de carga se mostrará indefinidamente en el navegador. No se mostrarán errores, ni siquiera por la consola, por lo que el usuario se quedará esperando sin saber que, en realidad, la aplicación no cargará jamás.

Lo que vamos a ver en este post es cómo detectar este escenario e informar al usuario de que para acceder a la aplicación debe usar un browser más moderno.

¿Cómo detectar si el navegador soporta Blazor WebAssembly?

Para que un browser pueda ejecutar una aplicación Blazor WebAssembly, el requisito obvio es que soporte WebAssembly. ¿Cómo hacemos esto?

Pues como siempre que lo necesitamos, StackOverflow viene al rescate (aunque he modificado ligeramente el código para hacerlo más legible para todos):

function wasmIsSupported() {
    try {
        if (typeof WebAssembly === "object"
            && typeof WebAssembly.instantiate === "function") {
            const module = new WebAssembly.Module(
                Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
            );
            if (module instanceof WebAssembly.Module)
                return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
        }
    } catch (e) {
    }
    return false;
};

Este código define la función wasmIsSupported() que:

  • Comprueba que el objeto WebAssembly está accesible.
  • Comprueba que dicho objeto dispone de una función instantiate().
  • Compila al vuelo un pequeño módulo WebAssembly y comprueba que funciona correctamente.
  • Si se superan todas las comprobaciones anteriores, se retornará el valor true.

Con esta parte solucionada, sólo nos queda utilizarla en la inicialización de la página para detectar el soporte WebAssembly justo antes de arrancar la aplicación.

Tomar el control del arranque para notificar al usuario

Algunas entradas atrás, cuando hablábamos de interoperación con Javascript, vimos que las aplicaciones Blazor WebAssembly arrancan automáticamente al cargarse el cliente ligero blazor.webassembly.js que introducimos en las páginas, pero que podíamos modificar este comportamiento para hacerlo de forma manual.

Como recordatorio, esto podíamos conseguirlo estableciendo a false el atributo autostart de la etiqueta script:

<script src="_framework/blazor.webassembly.js" autostart="false"></script>

Hecho esto, la aplicación Blazor ya no arrancará automáticamente; para hacerlo, tendremos que ejecutar de forma manual el método Blazor.start() en el momento que nos interese.

Combinando esto con la detección de WebAssembly que vimos más arriba, podemos crear un bloque de script que arranque Blazor sólo si se soporta WebAssembly, o que muestre un alert() para informar al usuario en caso contrario:

if (wasmIsSupported()) {
    Blazor.start();
}
else {
    alert("Lo sentimos, pero su navegador es demasiado antiguo " + 
          "para ejecutar esta aplicación. Pulse aceptar para salir.");
    location.href = "https://www.google.es";
}

Así pues, el código completo que deberíamos incluir en la página sería:

...
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
    function wasmIsSupported() {
        try {
            if (typeof WebAssembly === "object"
                && typeof WebAssembly.instantiate === "function") {
                const module = new WebAssembly.Module(
                    Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
                );
                if (module instanceof WebAssembly.Module)
                    return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
            }
        } catch (e) {
        }
        return false;
    };

    if (wasmIsSupported()) {
        Blazor.start();
    }
    else {
        alert("Lo sentimos, pero su navegador es demasiado antiguo " + 
              "para ejecutar esta aplicación. Pulse aceptar para salir.");
        location.href = "https://www.google.es";
    }
</script>

Y en tiempo de ejecución tendríamos lo siguiente:

Obviamente en lugar de un alert() podríamos redirigir directamente a otra página para describir el error, o mostrar directamente un mensaje algo más trabajado, pero eso os lo dejo como deberes ;)

Publicado en Variable not found.

2 Comentarios:

He vuelto :D dijo...

Hacía años que no entraba directamente en tu blog, siempre lo leo vía RSS, y me ha resultado muy chocante la interfaz gráfica tan retro. Señor Aguilar, creo que va siendo de aplicar un lavado de cara a este pozo de sabiduría que es tu blog.

José María Aguilar dijo...

Hola!

Ya, es algo que tengo en mi backlog desde hace años... el problema es que es un tema que tendría bastante trabajo y no tengo tiempo para dedicarle. Bueno, y aparte tampoco es que se me dé demasiado bien el tema del diseño, claro...

En fin, ya se hará ;)