Um dos pontos negativos do Blazor WASM em relação aos frameworks tradicionais Javascript é que ele nunca vencerá no quesito tamanho final da aplicação. Mas é possível reduzir significativamente o pacote final entregue com algumas medidas que vou apresentar aqui.
O Trimmer do .NET (IL Linker) analisa os assemblies da aplicação e realiza o “corte” do que não é utilizado.
Imagine uma propriedade nunca utilizada de uma classe, o Trimmer consegue perceber isso e remover do Assembly correspondente, reduzindo seu tamanho.
No .NET 6 o trimming ocorre automaticamente em publicações em modo release, dotnet publish -c Release
, desde que você tenha instalado o .NET WebAssembly Tools, recurso opcional do Visual Studio.
Eu consegui fazer o trimming funcionar também em um Github Action Linux realizando, antes da compilação, o comando dotnet workload install wasm-tools
.
Esta primeira medida deve reduzir em 55kB (de 854kB para 799kB) o tamanho já comprimido do arquivo dotnet.wasm
.
Esta opção é ativada no csproj
do projeto Blazor desta forma:
<PropertyGroup>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
Isso significa que você não poderá realizar as tradicionais formatações de números e datas em outra cultura que não seja en-US
.
Eu acredito que a adição desta limitação vale a pena pela significativa redução de tamanho adquirida. Eu consigo contornar a ausência deste recurso com formatações mais manuais como:
decimal x = 12300m;
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ",";
nfi.NumberGroupSeparator = ".";
Console.WriteLine(x.ToString("#,##0.00", nfi));
e em datas
algumaData.ToString("dd/MM/yyyy");
Com essa opção, o dotnet.wasm
reduziu de 799kB para 359kB
Para realizar essa remoção será necessário adicionar esta outra opção no csproj
:
<PropertyGroup>
...etc...
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
</PropertyGroup>
Creio que não vou sentir falta deste. Isso vai impossibilitar a conversão de datas entre TimeZones.
Assim como o InvariantGlobalization, se eu sentir alguma falta no projeto em que estou trabalhando então voltarei aqui para atualizar este artigo explicando o motivo.
Com esta medida será eliminado o arquivo dotnet.timezones.blat
, removendo 44kB do pacote da aplicação.
A publicação do Blazor gera versões gz
(Gzip) e br
(Brotli) dos arquivos da pasta _framework
. O ASP.NET Core também já serve automaticamente a versão comprimida desses arquivos.
Mas para outros arquivos estáticos na pasta wwwroot isso não acontece. Você pode utilizar alguma ferramenta para gerar as versões comprimidas dos outros arquivos.
No meu caso, utilizo GitHub Actions para compilar e publicar minha aplicação e lá encontrei uma Action pronta que já cria as versões .gz
e .br
dos arquivos.
É esta aqui:
- name: compress wwwroot/_content
uses: StefH/ghaction-CompressFiles@v1
with:
path: Pack/wwwroot/_content
Se você está usando ASP.NET Core para servir sua aplicação BlazorWASM, é necessário também fazer com que ele sirva esses arquivos pré-comprimidos.
Para isso encontrei um pacote NuGet que resolve esta questão =>
Instale esse pacote no projeto Server e então, no Program.cs/Startup.cs adicione o serviço:
services.AddCompressedStaticFiles();
E substitua app.UseStaticFiles()
por:
app.UseCompressedStaticFiles()
Com isso eu acabei reduzindo o tamanho da aplicação em cerca de +800kB!
No projeto em que estou trabalhando usamos o MudBlazor, e ele possui um css com cerca de 504kB. Com a compressão o arquivo ficou com 35.3kB(Brotli).
Para uma biblioteca ser afetada pelo trimming ela precisa declarar que isso pode ser feito nela.
Como eu mencionei no tópico anterior, estamos utilizando MudBlazor no projeto e descobri que alguns dias atrás eles lançaram uma nova versão trimável.
Essa versão, com numeração 6.0.11
, foi publicada no dia 01/07/2022. Antes desta versão, a dll do MudBlazor servida estava, em sua versão comprimida, com 997kB. Após a atualização a ddl ficou com 128kB!!!
Após todas essas medidas, o donwload inicial da aplicação reduziu de 4.5MB para 2.0MB.
Creio que eu ainda conseguiria otimizar algumas imagens, reduzindo o pacote total para 1.8MB.
Dependendo do porte do projeto, ainda é possível aproveitar o recurso de Lazy Loading de assemblies.
O tamanho final não ficou tão baixo comparado ao que conseguimos fazer com frameworks javascript tradicionais, mas creio que está dentro do que considero aceitável. O Blazor ainda é muito novo, assim como o WebAssembly e creio que haverá muitas melhorias pela frente.
Ficaremos de olho.