.NET 6  - Novidades para o Blazor


Hoje vou apresentar as principais novidades para o Blazor disponíveis no .NET 6.

O .NET 6 está chegando e, com ele, algumas melhorias notáveis do Blazor, como : Componentes dinâmicos, hot reload, aplicativos Blazor MAUI, etc.,  a lista não é pequena, e, neste artigo veremos as principais novidades. (Reproduzido a partir do artigo original com alterações)

1 - Blazor : Componentes dinâmicos

Um DynamicaComponent é um novo componente Blazor que pode ser usado para renderizar de forma dinâmica um componente específico pelo tipo.


<DynamicComponent Type="@algumTipo" />
 

Ele também oferece suporte a parâmetros que podem ser passados para o componente renderizado usando um Dictionary:

<DynamicComponent Type="@algumTipo" Parameters="@meuDictionaryDeParâmetros" />

@code {
     Type algumTipo= ...
      IDictionary<string, object> meuDictionaryDeParâmetros= ...
}

Para mais detalhes veja o meu artigo :  NET 6  - Blazor : Componentes Dinâmicos

2- Blazor : Hot Reload

O desenvolvimento moderno da web envolve fazer pequenas alterações em HTML, CSS, lógica da IU e é difícil iterar rapidamente seu design quando você está esperando para ver essas mudanças ganharem vida no navegador.

Melhorar esse ciclo de feedback era uma prioridade para .NET 6, e as versões preview do .NET 6 mostraram melhorias constantes a cada versão.

O suporte ao Hot Reload agora existe para Visual Studio e dotnet watch(*) e, em geral, está funcionando bem. O efeito é uma atualização quase instantânea no navegador quando você ajusta seus componentes e se, por qualquer motivo, o hot reload falhar, você será perguntado se deseja realizar uma reconstrução completa (com uma opção para sempre faça isso no futuro).

(*) - Na reta final parece que a funcionalidade havia sido excluída do .NET CLI, mas diante da reação da comunidade a Microsoft voltou atrás e o recurso vai continuar existindo no .NET CLI.

Para mais detalhes veja o meu artigo :  NET 6  - Blazor : Componentes Dinâmicos

3- Blazor : Compilação Ahead of Time (Wasm)

O Blazor WebAssembly agora oferece suporte à Compilação Antecipada (AOT), mas antes de você sair correndo para habilitá-lo para todos os seus projetos, vale a pena apenas fazer uma pausa para considerar o que isso realmente significa para o seu aplicativo.

A Compilação Ahead of Time(AOT) compila diretamente seu código .NET para WebAssembly como parte do processo de compilação.

Isso é diferente da maneira padrão como seus aplicativos Blazor Wasm são executados hoje, onde seu código nunca é compilado para WebAssembly, em vez disso executado em um interpretador .NET IL (que é implementado em WebAssembly).

Esse uso de um intérprete significa, na prática, que seu aplicativo Blazor Wasm padrão terá um desempenho mais lento do que em um runtime .NET normal (por exemplo, um aplicativo MVC ou Razor Pages em execução em um servidor).

A AOT resolve esse problema de desempenho compilando seu código para WebAssembly. Para tarefas com uso intensivo de CPU, a melhoria de desempenho é significativa (até 5 vezes mais rápida), mas a compilação AOT traz suas próprias compensações.

Requer a instalação de uma ferramenta de compilação adicional, a compilação real em si é bastante lenta (a partir do Preview 7) e os aplicativos compilados AOT são maiores (cerca de 2x maiores em média).

Para instalar as ferramentas .NET WebAssembly mais recentes para compilação antecipada (AOT) e revinculação do tempo de execução, desinstale a carga de trabalho microsoft-net-sdk-blazorwebassembly-aot anterior e instale a nova carga de trabalho wasm-tools executando os seguintes comandos de um prompt de comando elevado:


   dotnet workload uninstall microsoft-net-sdk-blazorwebassembly-aot
   dotnet workload install wasm-tools  
  

 

A principal desvantagem deste recurso é que você vai sacrificar o tempo de carregamento em prol do desempenho do runtime, então a decisão se isso faz sentido irá variar dependendo do aplicativo específico que você está construindo.

4- Blazor : Parâmetros de Componentes via Query String

A partir do .NET 6 preview 7, você pode preencher os parâmetros do componente a partir da query string ou string de consulta.

Você já podia fazer isso anteriormente, mas precisava recorrer aos recursos do namespace Microsoft.AspNetCore.WebUtilities e escrever seu próprio código para lidar com isso.

Agora é muito mais simples, pois você pode simplesmente decorar seus parâmetros com o novo atributo SupplyParameterFromQuery:


   [Parameter]
   [SupplyParameterFromQuery]
   public string Filtro { get; set; }     
  

Usando este recurso você pode anexar  ?Filtro=x na URL da sua página Blazor, e, o parâmetro correspondente (Filtro) será preenchido com o valor da string de consulta.

Os parâmetros do componente fornecidos a partir da string de consulta podem ser dos seguintes tipos:

Atualmente há um debate em andamento sobre o nome do atributo, então ele pode mudar em uma versão futura, mas a funcionalidade permanecerá a mesma.

5- Blazor : Parâmetros Requeridos

Agora se o seu componente depende de um determinado parâmetro, você pode garantir que esse parâmetro seja sempre fornecido marcando o parâmetro como EditorRequired.

   [EditorRequired]
   [Parameter]
   public string Name { get; set; }     
  

Se você tentar usar o componente sem especificar os parâmetros necessários, receberá um erro em tempo de desenvolvimento (em seu IDE e/ou quando o aplicativo for compilado).



É importante notar que o recurso não é aplicado em tempo de execução, e, portanto, não garante que os valores dos seus parâmetros não serão nulos.

6- Blazor : Modificar cabeçalho HTML

Agora com o suporte direto para atualizar o cabeçalho HTML de seus componentes e isso tornará alguns cenários muito mais fáceis de tratar.

Você pode alterar facilmente o título da página e adicionar metatags para SEO sem recorrer à interoperabilidade JS para fazer o trabalho.

Para isso, o .NET 6 apresenta dois novos componentes: PageTitle e HeadContent.

Você pode alterar o título da página usando PageTitle.

<PageTitle>@titulo</PageTitle>

@code
{
     private string titulo = "Título da Página!"   
}
 

E pode adicionar o que você desejar no HTML da tag <head> usando HeadContent:

<HeadContent>
<meta name="description" content="@descricao">
</HeadContent>

@code
{
      private string descricao = "Descrição dinâmica do recurso HeadContent do Blazor"
}

Para habilitar a funcionalidade fornecida por PageTitle e HeadContent, você precisa adicionar um componente raiz HeadOutlet ao seu aplicativo.

No Blazor WebAssembly, isso pode ser feito adicionando na seguinte linha em Program.Main:


  builder.RootComponents.Add<HeadOutlet>("head::after");   
 

No Blazor Server, a configuração é um pouco mais complicada. Para oferecer suporte à pré-renderização, o componente raiz do aplicativo precisa ser renderizado antes do HeadOutlet. Uma maneira conveniente de fazer isso é mover a maior parte do conteúdo de _Host.cshtml para _Layout.cshtml.  

A partir da versão RC1 os templates já vem com esta funcionalidade habilitada.

7- Blazor :  Error Boundaries (Limites de erros)

Com a versão atual/anterior do Blazor, qualquer exceção lançada em qualquer componente geralmente resultaria na falha de todo o aplicativo, geralmente exigindo a reinicialização de todo o aplicativo.

Com o .NET 6, você pode conter o caos e envolver qualquer parte de seu aplicativo em um limite de erro usando a tag <ErrorBoundary> :

<h1>Super Fancy Application</h1>
<div>
    <ErrorBoundary>
    	<Counter />
    </ErrorBoundary>
</div>

Agora, se Counter lançar uma exceção, um erro será exibido onde o ErrorBoundary é declarado, deixando o resto da IU inalterado.

Por padrão, os limites de erro renderizam uma div vazia com uma classe CSS blazor-error-boundary quando ocorre uma exceção. No entanto, você pode ter mais controle desse erro se desejar:

h1>Aplicação Blazor Demo</h1>
<div>
    <ErrorBoundary>
        <ChildContent>
            <Counter />
        </ChildContent>
    <ErrorContent>
        <p class="bad-error">
               Ocorreu um erro ao executar o contador...
            </p>
        </ErrorContent>
    </ErrorBoundary>
</div>

8- Blazor - Pré-renderização aprimorada com estado preservado

Você sabia que pode optar por pré-renderizar seus aplicativos Blazor Wasm no servidor?

Isso fornece uma experiência do “melhor dos dois mundos”, em que o tempo de carregamento inicial do seu aplicativo Blazor é rápido (porque a página é renderizada no servidor e retornada como HTML direto), mas então seus componentes tornam-se totalmente interativos no navegador assim que o Blazor Wasm terminou de carregar.

No entanto, havia uma grande ressalva para isso no .NET 5, onde as páginas orientadas a dados carregam uma vez (após a pré-renderização) e, em seguida, potencialmente ocorria um "flash", conforme os dados eram recuperados pela segunda vez no navegador (uma vez que o Blazor Wasm foi iniciado).

No .NET 6 houve uma melhoria bem-vinda por meio da qual você pode armazenar o estado inicial (quando o aplicativo é pré-renderizado) e usá-lo para o segundo carregamento, eliminando assim a necessidade de buscar os mesmos dados duas vezes (removendo também o "flash" do conteúdo no navegador após o segundo carregamento).

Para usá-lo, você deve primeiro adicionar a tag <persist-component-state> dentro da tag de fechamento </body> de sua página _Layout.cshtml.

<body>
...

<persist-component-state />

</body>
 

Em seguida, você pode registrar um manipulador para o evento OnPersisting de PersistentComponentState no(s) componente(s) em que deseja preservar o estado. Exemplo:

@page "/fetchUsers"
@implements IDisposable
@
inject PersistentComponentState ApplicationState

<!-- html aqui -->   

@code {
      private IEnumerable<User> users;
      private PersistingComponentStateSubscription _subscription;
   

    protected override async Task OnInitializedAsync()
    {
        _subscription = ApplicationState.RegisterOnPersisting(PersistUsers);
     

        if (ApplicationState
            .TryTakeFromJson<User[]>("users", out var storedUsers))
        {
            users = storedUsers;          
        } else {
             users = await UserService.GetUsersAsync();
        }
    }

    private Task PersistUsers()
    {
        ApplicationState.PersistAsJson("users", users);
        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
         _subscription.Dispose();
    }  

}

Neste código PersistentComponentState e, consequentemente, podemos registrar um evento OnPersisting para buscar e, em seguida, persistir os dados do usuário.

No carregamento subsequente (no navegador, via Blazor Wasm), o método OnInitializedAsync tentará recuperar a lista de usuários do estado persistente primeiro, apenas revertendo para buscar os usuários por meio do UserService se os dados persistentes não forem encontrados.

9- Blazor - Melhorias de desempenho

Existem também inúmeras melhorias de desempenho para o Blazor chegando no .NET 6.

Um destaque é o tamanho de download reduzido do Blazor Wasm, graças ao novo relinking aprimorado e estendido na nova versão.

Revincular é o processo pelo qual o código não utilizado pode ser cortado das bibliotecas, tornando-as menores e, portanto, reduzindo o tamanho do download do aplicativo compilado.

Já existe uma nova vinculação para eliminar o código não utilizado das bibliotecas do .NET Core, mas no .NET 6 isso está sendo estendido para o próprio runtime do .NET.

No geral, isso resultará em um download do dotnet.wasm menor, mas há uma área onde você pode reduzir significativamente esse tamanho ainda mais.

Se você sabe que não precisa lidar com strings, números, datas, etc. de forma diferente com base na cultura atual (de acordo com o navegador do usuário), então você pode  desativar a funcionalidade de globalização para seu aplicativo.

Ao definir InvariantGlobalization como true em seus arquivos de projeto, a lógica relacionada no runtime do .NET será removida, tornando o runtime consideravelmente menor.

Se você gosta de usar projetos Blazor Server, ficará satisfeito em saber que o .NET 6 vem com scripts de servidor Blazor menores também, tornando a inicialização mais rápida.

O compilador Razor foi atualizado para usar geradores de código-fonte (resultando em uma compilação mais rápida de suas visualizações do Razor).

Também há melhorias no upload de arquivos, com arquivos maiores que 2 GB agora suportados usando o componente InputFile e upload muito mais rápido graças ao streaming nativo de byte [].

10 - Blazor  - Acessibilidade

É sempre uma boa hora para se concentrar em tornar seu aplicativo mais acessível, e a nova versão do Blazor o leva na direção certa.

Há um novo componente FocusOnNavigate que definirá o foco da IU para um elemento de sua escolha (com base em um seletor CSS) após navegar para uma página.

Você encontrará o componente em uso no componente App ao ativar um aplicativo Blazor usando .NET 6.

<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

Além disso, você também encontrará algumas alterações no modelo padrão do Blazor que ajudam a garantir que seu aplicativo esteja acessível desde o início.

- Atributos role="alert" e role="status" usados nos componentes de exemplo (como o contador)
- Uso de mais elementos de marcação semântica (main e article em vez de div)
- nav em vez de ul no componente NavBar
- Atributo title adicionado ao botão de alternância da NavBar;

Todas essas alterações podem ajudar a garantir que seu aplicativo seja acessível e funcione melhor com leitores de tela.

11- Blazor - .NET MAUI

O .NET MAUI é a evolução do Xamarin Forms. Seu objetivo é facilitar a construção de aplicativos multiplataforma sem exigir que você, o desenvolvedor, escreva o mesmo código repetidamente para as diferentes plataformas.

Com o .NET MAUI você pode criar um projeto, construir seu aplicativo e executá-lo em Android, iOS, macOS e Windows.

A principal maneira de construir um aplicativo MAUI é usando C # e XML, mas com o .NET 6 também temos o primeiro vislumbre de outra opção: construir aplicativos MAUI usando Blazor.

Se você achar agradável e produtivo construir seus aplicativos da web usando o modelo de componente do Blazor, então você pode adotar a mesma abordagem e construir seus aplicativos MAUI usando o Blazor.

Dessa forma, quando você compilar seu aplicativo, ele será executado como um aplicativo nativo, como qualquer outro aplicativo MAUI.

Isso lhe dá o benefício de escrever seus aplicativos usando o paradigma familiar do modelo de componente do Blazor, mas com o benefício adicional de acesso total aos recursos nativos dos dispositivos nos quais seu aplicativo será executado.

Em suma, se você precisa criar aplicativos para Android, iOS, Windows e / ou MacOS, os aplicativos .NET MAUI Blazor tornam isso possível usando o modelo de componente do Blazor.

Conclusão

Estas são as principais novidades da versão do Blazor no .NET 6, mas existem outros recursos que não foram apresentados aqui como : suporte para eventos personalizados, controles .BlazorWebView para WPF e Windows Forms, suporte aprimorado para Blazor SVG, etc.

Para se manter atualizado com as novidades configura o blog oficial da ASP.NET.

"E, ao pôr do sol, todos os que tinham enfermos de várias doenças lhos traziam; e, pondo as mãos sobre cada um deles, 'Jesus' os curava."
Lucas 4:40


Referências:


José Carlos Macoratti