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, 20 de abril de 2021
Blazor

Cuando empezamos a estudiar Blazor WebAssembly e interiorizamos que para ejecutar .NET en el navegador es necesario llevar hasta éste el runtime y bibliotecas, tanto del propio framework como las de nuestra aplicación, una de las primeras dudas que nos asaltan es que cuánto peso tendrá eso. O dicho de otra forma, qué recursos tendrán que descargar los usuarios y qué tiempo tendrán que esperar hasta tener la aplicación en funcionamiento.

En este post vamos a intentar dar respuesta a esta pregunta, aunque con matices. Obviamente, parte de ese peso dependerá de la aplicación; si se trata de un proyecto grande, con muchos ensamblados o que usen muchos componentes externos (p.e. paquetes NuGet), el número de archivos y el tamaño de la descarga crecerá inexorablemente. Por esa razón, no podremos ver aquí números absolutos, sino los mínimos, es decir, lo que pesará una aplicación Blazor WebAssembly recién creada, con los contenidos proporcionados por la plantilla por defecto usando .NET 5.

Tampoco hablaremos de tiempos, pues son totalmente dependientes de las condiciones de red, la infraestructura en la que despleguemos la aplicación y las posibilidades del cliente. Simplemente tendremos en consideración que a más peso, mayor tiempo será necesario para llevarlo al navegador y ejecutarlo.

Ojo: lo que vamos a ver son los datos aproximados obtenidos en mi máquina de desarrollo y con la versión actual de Blazor (5.0.4). Los números exactos variarán si hacéis pruebas en vuestro entorno, aunque seguro que el espíritu de las conclusiones seguirá siendo el mismo.

Escenario 1: aplicación ejecutada en el entorno de desarrollo por primera vez

Acabamos de crear una aplicación Blazor WebAssembly con Visual Studio y pulsamos F5.

Peticiones realizadas 204
Contenido transferido (comprimido) 9.2 MB
Contenido cargado en la página (descomprimido) 22.8 MB

Panel de red en las herramientas de desarrollador, mostrando gran cantidad de recursos descargados ¿De dónde salen estos números tan altos? Pues hay que tener en cuenta varios factores:

  • Estamos descargando, además de la página "raíz" que actúa como lanzadora de la aplicación y sus recursos relacionados (CSS, JS, iconos, fuentes), entre otros:
    • El runtime WebAssembly de .NET
    • Archivos de manifiesto y configuraciones
    • Los ensamblados (*.dll) de .NET 5
    • Los ensamblados de nuestra aplicación
    • Los datos de zonas horarias
  • El entorno de ejecución es Development, por lo que no se aplica ningún tipo de optimización.
  • No tenemos nada en caché, por lo que nuestro navegador deberá descargar todos los recursos.

Aunque en nuestra máquina local o en redes internas la descarga de esos más de 9 MB no suponga ningún problema, en otro tipo de conexiones sí podría resultar un retraso importante para la carga. Sin embargo, recordad: estamos en el entorno de desarrollo y es la primera vez que ejecutamos.

Escenario 2: aplicación ejecutada en el entorno de desarrollo por segunda vez o sucesivas

Tras la primera ejecución, detenemos el proyecto y lo volvemos a lanzar desde Visual Studio pulsando la tecla F5.

Peticiones realizadas 11
Contenido transferido (comprimido) 5.6 kB
Contenido cargado en la página (descomprimido) 529 kB

¡Uau! ¡Pues sí que cambió la cosa! En la primera carga gran parte de los recursos (en particular, el runtime y bibliotecas de .NET) se almacenaron en la caché del navegador, por lo que no fue necesario volver a obtenerlos.

Los contenidos cacheados son almacenados junto con un hash que permite detectar cuándo han cambiado. No se volverán a descargar salvo que eliminemos la caché o su contenido sea modificado.

Nota: estos recursos son almacenados el cache storage, que es distinto al caché habitual del navegador, pues es gestionado desde el código JS de la página. Por esta razón, el comportamiento de opciones como "Disable caching" en la pestaña de red del navegador no tendrán efecto.

Escenario 3: aplicación ejecutada en el entorno de desarrollo tras haber sido modificada

Volvemos a lanzar con F5, aunque previamente modificamos ligeramente uno de los componentes Blazor, forzando así la generación de un nuevo ensamblado del proyecto.

Peticiones realizadas 12
Contenido transferido (comprimido) 51.2 kB
Contenido cargado en la página (descomprimido) 555 kB

Como podemos observar, se trata de unos números muy parecidos a los anteriores. La diferencia principal está en el ensamblado del proyecto, que al haber sido modificado es necesario obtenerlo de nuevo. El resto de elementos previamente cacheados siguen siendo válidos.

Escenario 4: aplicación publicada y ejecutada por primera vez

Hasta ahora hemos visto los números siempre en el entorno de desarrollo, por lo que sólo nos afectarían mientras trabajamos en el proyecto. Pero pasemos a un escenario más definitivo: publicamos la aplicación (compilada en modo "Release") y la lanzamos, eliminando previamente la caché del navegador.

Peticiones realizadas 47
Contenido transferido (comprimido) 2.1 MB
Contenido cargado en la página (descomprimido) 7.0 MB

¡Hey! ¿Qué ha pasado aquí? Pues en primer lugar, fijaos en la reducción tan brutal del número de peticiones realizadas: hemos pasado de más de 200 a menos de 50. La magia aquí está en el IL trimming de la publicación, un mecanismo que permite eliminar de la salida el código IL que no utilizamos en la aplicación, incluidos los ensamblados del propio framework.

También podemos observar una reducción importante en el tamaño (de 9 a 2MB). Aparte de que se han descargado menos recursos, esta reducción también se debe a que durante la publicación los archivos resultantes son comprimidos de forma estática.

Como podemos ver, estos datos son bastante satisfactorios. Tanto el número de archivos a descargar como su peso total son más que razonables, teniendo en cuenta además que esta carga sólo ocurrirá la primera vez.

Escenario 5: aplicación publicada en modo release y ejecutada por segunda vez (o siguientes)

Accedemos de nuevo a la aplicación publicada anteriormente manteniendo la caché en el navegador, que al fin y al cabo será el comportamiento habitual de nuestros usuarios.

Peticiones realizadas 10
Contenido transferido (comprimido) 5.8 Kb
Contenido cargado en la página (descomprimido) 514 Kb

Como podemos ver en este caso, una vez el contenido se encuentra en el navegador, queda poco por descargar, por lo que los resultados son similares a los que veíamos en tiempo de desarrollo. Números bastante bajos teniendo en cuenta que se trata de una recarga completa .

Conclusión

Como hemos visto, lo maravilloso que resulta poder utilizar C# en el navegador tiene su coste en cuanto a tiempo de la primera carga de la aplicación, aunque éste se reduce de forma drástica cuando nos encontramos en un entorno de producción y cuando se trata de las cargas sucesivas, gracias al uso de la caché del navegador.

En muchos escenarios probablemente este retraso en el primer acceso es totalmente asumible. Si no es nuestro caso, probablemente deberíamos evaluar el uso de opciones que "maquillan" esos tiempos, como la prerenderización en servidor o el uso de animaciones o efectos interesantes para hacer más grata esa espera inicial a nuestros usuarios. Otras veces, cuando el tiempo inicial sea un factor absolutamente crítico, no tendremos más remedio que optar por tecnologías más ligeras en cliente (incluyendo Blazor Server, que es una buena opción en algunos escenarios).

Publicado en Variable not found.

2 Comentarios:

chankly dijo...

Lo que si me choca y he tenido varios problemas es con la caché que no actualiza. Si haces una página blazor web assembly (no SPA), con archivo de recursos, ficheros javascript referenciados en su index.html y después haces una actualización de la página (la despliegas de nuevo), este no hace caso de los cambios..

Estoy invenstigando como arreglar el problema, pero desde luego que hay alguna .dll que le cuesta actualizar.

José María Aguilar dijo...

Hola,

pues la verdad es que no sabría decirte... realmente, si despliegas de nuevo los ensamblados y en el browser refrescas la página, debería actualizarse :(

Si descubres algo, me encantaría oírlo ;)

Muchas gracias!