Codeblox Blog

Reduzindo o tamanho de uma aplicação Blazor WASM

Guilherme
25/07/2022

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.

1. Verificar se o Trimming está habilitado

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.

2. Se possível, utilize InvariantGlobalization

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

3. Remover, se possível, o suporte a TimeZones

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.

4. Comprimir arquivos da pasta wwwroot

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 => NuGet version Nuget

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).

5. Verifique se está com a versão mais recente das bibliotecas

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!!!

6. Conclusão

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.

blazor
webassembly
csharp
dotnet


Guilherme M. Abdo
Guilherme M. Abdo
Desenvolvedor fullstack .Net/Angular/Azure/GitHub