.NET 9 Blazor: Desenvolvimento Full-Stack com Blazor United em 2026

.NET 9 Blazor United combina renderização estática SSR, Server e WebAssembly em um framework full-stack unificado. Tutorial prático cobrindo modos de renderização, streaming, injeção por construtor e padrões prontos para produção.

Desenvolvimento full-stack com .NET 9 Blazor United e múltiplos modos de renderização

Blazor United no .NET 9 une três estratégias de renderização — renderização estática do lado do servidor (SSR), Server interativo e WebAssembly — em um único framework full-stack coeso. Esse modelo unificado, introduzido no .NET 8 e aprimorado no .NET 9, elimina a necessidade de escolher entre diferentes modelos de hospedagem do Blazor antes mesmo de escrever a primeira linha de código.

Blazor United em resumo

Blazor United permite combinar SSR estático, interatividade Server e interatividade WebAssembly dentro da mesma aplicação. Cada componente declara independentemente seu modo de renderização, proporcionando controle granular sobre desempenho e interatividade por página.

Configurando uma aplicação Blazor Web com .NET 9

O template blazorweb do .NET 9 gera um projeto pré-configurado para os três modos de renderização. A configuração requer o SDK do .NET 9 (versão 9.0.100 ou posterior) e cria tanto o projeto do servidor quanto o do cliente (WASM) em um único comando.

bash
# Criar uma nova Blazor Web App com todos os modos de renderização habilitados
dotnet new blazorweb -n FullStackApp --interactivity Auto --all-interactive false
cd FullStackApp
dotnet run

A flag --interactivity Auto habilita os modos de renderização Server e WebAssembly. O parâmetro --all-interactive false mantém a renderização estática SSR como padrão, de modo que a interatividade é ativada componente por componente em vez de globalmente.

Entendendo os modos de renderização do Blazor no .NET 9

Cada componente em uma Blazor Web App adota um modo de renderização que determina onde ele é executado, se suporta interatividade e como se comunica com o servidor. O .NET 9 oferece quatro modos distintos.

Modo de renderizaçãoHospedagemInteratividadeIdeal para
SSR estáticoServidorNenhumaPáginas de marketing, documentação, conteúdo SEO
Interactive ServerServidor via SignalRCompletaDashboards, CRUD, formulários
Interactive WebAssemblyNavegador via WASMCompletaModo offline, lógica intensiva no cliente
Interactive AutoServidor depois WASMCompletaO melhor dos dois mundos — carregamento rápido + independência

O modo de renderização é definido no nível do componente com a diretiva @rendermode. Essa granularidade por componente significa que uma única página pode mesclar seções estáticas e interativas.

Components/Pages/Dashboard.razorcsharp
@page "/dashboard"
@rendermode InteractiveServer

<PageTitle>Dashboard</PageTitle>

<h1>Real-Time Metrics</h1>

<!-- This component renders interactively via SignalR -->
<MetricsChart />

<!-- Static content below renders as plain HTML -->
<footer>Updated every 5 seconds</footer>

Uma adição na API do .NET 9 — ComponentBase.RendererInfo — permite que os componentes detectem seu modo de renderização atual em tempo de execução, possibilitando lógica condicional baseada no contexto de execução.

Components/Shared/AdaptiveComponent.razorcsharp
@if (RendererInfo.IsInteractive)
{
    <button @onclick="HandleClick">Interactive Action</button>
}
else
{
    <a href="/fallback">Static Fallback Link</a>
}

@code {
    private void HandleClick()
    {
        // Runs only in interactive modes (Server or WASM)
    }
}

Renderização em streaming para páginas com carga assíncrona

Páginas SSR estáticas que buscam dados de forma assíncrona podem bloquear a resposta até que todas as tarefas sejam concluídas. A renderização em streaming resolve esse problema enviando HTML de placeholder imediatamente e, em seguida, transmitindo o conteúdo final conforme os dados chegam. No .NET 9, o atributo [StreamRendering] não requer mais o parâmetro true — ele é habilitado por padrão.

Components/Pages/Products.razorcsharp
@page "/products"
@attribute [StreamRendering]

<PageTitle>Product Catalog</PageTitle>

@if (products is null)
{
    <p>Loading products...</p>
}
else
{
    <div class="product-grid">
        @foreach (var product in products)
        {
            <ProductCard Item="@product" />
        }
    </div>
}

@code {
    private List<Product>? products;

    // Data loads asynchronously; streaming pushes updates to the browser
    protected override async Task OnInitializedAsync()
    {
        products = await ProductService.GetAllAsync();
    }
}

A renderização em streaming utiliza a codificação de transferência em partes (chunked transfer encoding) do HTTP/1.1, compatível com todos os navegadores modernos. O conteúdo de placeholder é exibido instantaneamente, e a marcação final o substitui sem recarregamento completo da página.

Injeção por construtor em componentes Blazor

O .NET 9 introduz a injeção por construtor para componentes Blazor, complementando a diretiva @inject e o atributo [Inject] existentes. Combinada com os construtores primários do C# 12, as dependências de serviços se tornam parte da assinatura de tipo do componente.

Components/Pages/OrderHistory.razorcsharp
@page "/orders"
@rendermode InteractiveServer

<h2>Order History</h2>

@if (orders is not null)
{
    <table>
        <thead>
            <tr><th>Order ID</th><th>Date</th><th>Total</th></tr>
        </thead>
        <tbody>
            @foreach (var order in orders)
            {
                <tr>
                    <td>@order.Id</td>
                    <td>@order.PlacedAt.ToShortDateString()</td>
                    <td>@order.Total.ToString("C")</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    // Constructor injection via primary constructor
    [Inject] public required IOrderService OrderService { get; set; }
    [Inject] public required NavigationManager Nav { get; set; }

    private List<Order>? orders;

    protected override async Task OnInitializedAsync()
    {
        orders = await OrderService.GetRecentOrdersAsync();
    }
}

A injeção por construtor torna as dependências explícitas e simplifica os testes unitários. Os serviços registrados em Program.cs são resolvidos automaticamente, incluindo os serviços com chave adicionados via builder.Services.AddKeyedScoped<T>().

Pronto para mandar bem nas entrevistas de .NET?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Modo Interactive Auto — o melhor dos dois mundos

O modo Auto oferece o menor tempo de carregamento percebido. Na primeira visita, o componente é executado no servidor via SignalR enquanto o runtime do WebAssembly é baixado em segundo plano. Nas visitas seguintes, a execução passa inteiramente para o navegador.

Components/Pages/Chat.razorcsharp
@page "/chat"
@rendermode InteractiveAuto

<h2>Live Chat</h2>

<div class="chat-messages">
    @foreach (var msg in messages)
    {
        <div class="message">@msg.Author: @msg.Text</div>
    }
</div>

<input @bind="newMessage" @onkeydown="HandleKey" placeholder="Type a message..." />

@code {
    [Inject] public required IChatService ChatService { get; set; }

    private List<ChatMessage> messages = new();
    private string newMessage = string.Empty;

    protected override async Task OnInitializedAsync()
    {
        messages = await ChatService.GetRecentMessagesAsync();
    }

    private async Task HandleKey(KeyboardEventArgs e)
    {
        if (e.Key == "Enter" && !string.IsNullOrWhiteSpace(newMessage))
        {
            await ChatService.SendAsync(newMessage);
            newMessage = string.Empty;
        }
    }
}

O modo Auto exige que as dependências e a lógica do componente funcionem em ambos os contextos, servidor e WASM. Os serviços devem ser abstraídos por meio de interfaces e registrados nos contêineres de injeção de dependência tanto do servidor quanto do cliente.

Reconexão e resiliência no .NET 9

O .NET 9 reescreve a lógica de reconexão do Blazor Server com uma estratégia de backoff exponencial. Em vez de tentar novamente em intervalos fixos, o framework começa com tentativas rápidas e aumenta progressivamente o intervalo — reduzindo a carga do servidor durante interrupções e recuperando-se rapidamente de falhas breves.

Melhorias principais:

  • Navegar de volta a uma aba dispara uma tentativa de reconexão imediata
  • Se o servidor já liberou o circuito, a página é atualizada automaticamente
  • A interface padrão exibe "Reconectando ao servidor..." com um indicador de progresso
  • Os intervalos de nova tentativa são configuráveis via Blazor.start()
wwwroot/app.js — Custom reconnection configurationjavascript
Blazor.start({
    circuit: {
        reconnectionOptions: {
            retryIntervalMilliseconds: (retryNumber) => {
                // Exponential backoff: 200ms, 400ms, 800ms, max 30s
                return Math.min(200 * Math.pow(2, retryNumber), 30000);
            },
            maxRetries: 15
        }
    }
});

SSR estático com interatividade seletiva

A arquitetura recomendada para a maioria das Blazor Web Apps em 2026 começa com SSR estático como padrão, adicionando interatividade apenas onde for necessário. O atributo [ExcludeFromInteractiveRouting] (novo no .NET 9) marca as páginas que devem permanecer estáticas — útil para páginas que dependem de cookies HTTP ou do ciclo de requisição/resposta.

Components/Pages/Privacy.razorcsharp
@page "/privacy"
@attribute [ExcludeFromInteractiveRouting]

<PageTitle>Privacy Policy</PageTitle>

<!-- This page always renders as static HTML -->
<!-- Even if global interactivity is enabled -->
<article>
    <h1>Privacy Policy</h1>
    <p>Last updated: April 2026</p>
    <!-- Content -->
</article>

Esse padrão funciona bem com MapStaticAssets, um novo middleware do .NET 9 que comprime e adiciona fingerprints aos arquivos estáticos no momento do build, substituindo a abordagem anterior de UseStaticFiles com uma entrega otimizada pronta para uso.

Ganhos de desempenho com a compilação AOT do .NET 9

A compilação AOT (Ahead-of-Time) do .NET 9 reduz o tamanho dos payloads do WebAssembly em até 40% em comparação com o .NET 8. A inicialização do Blazor WASM é 25% mais rápida segundo os benchmarks do Google Lighthouse. Esses ganhos são aplicados automaticamente ao publicar com AOT habilitado.

bash
# Publish with AOT for production
dotnet publish -c Release -p:RunAOTCompilation=true

A compressão de WebSocket também está habilitada por padrão para componentes interativos Server. Uma Content Security Policy (frame-ancestors: 'self') é aplicada automaticamente para mitigar vetores de ataque relacionados à compressão.

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Conclusão

  • Blazor United no .NET 9 elimina a decisão do modelo de hospedagem ao combinar SSR estático, Server e WebAssembly em um único projeto
  • Os modos de renderização são configurados por componente com @rendermode para otimizar cada página de forma independente — estático para SEO, Server para dashboards, Auto para cenários híbridos
  • A renderização em streaming com [StreamRendering] elimina atrasos de carregamento em páginas com alta carga assíncrona
  • A injeção por construtor (nova no .NET 9) torna as dependências dos componentes explícitas e testáveis
  • O modo Auto entrega um primeiro carregamento rápido via Server e depois muda para WASM para total independência do cliente
  • O backoff exponencial na reconexão reduz conexões perdidas e elimina recarregamentos manuais de página
  • A compilação AOT reduz o tamanho dos payloads WASM em 40% e o tempo de inicialização em 25%
  • Toda Blazor Web App deve começar com SSR estático como padrão e adicionar interatividade somente onde a experiência do usuário exigir

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Desafio do dia

Você saberia encontrar o bug em .NET?

Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador da SharpSkill

Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.

Atualizado em 26 de abril de 2026

Tags

#dotnet
#blazor
#aspnet-core
#webassembly
#full-stack

Compartilhar

Artigos relacionados