Start Debugging

Blazor Server vs Blazor WebAssembly vs Blazor United в .NET 11: что выбрать в 2026 году?

Для любого нового Blazor-приложения на .NET 11 создавайте Blazor Web App (шаблон, ранее известный как Blazor United) и выбирайте режим рендеринга для каждой страницы. Шаблоны только Server или только WebAssembly остаются оправданными лишь в узких случаях.

Для нового Blazor-проекта на .NET 11 ответ один: шаблон Blazor Web App (модель, которую во время preview .NET 8 называли “Blazor United”). Он позволяет выбирать рендеринг по компоненту: статический серверный рендеринг для маркетинговых страниц, интерактивный Server для CRUD-экранов с низкой задержкой, интерактивный WebAssembly для виджетов с поддержкой офлайн и Auto для компонентов, которые должны переключаться с Server на WebAssembly, как только загрузится пакет WASM. Шаблоны только Server или только WebAssembly стоит выбирать только при жёстком ограничении, исключающем унифицированную модель: внутреннее приложение, где загрузка WebAssembly недопустима, или PWA, которое должно работать полностью офлайн против сторонней API.

Эта статья ориентирована на .NET 11 (на момент написания в preview, GA запланирована на ноябрь 2026 года) и набор пакетов Microsoft.AspNetCore.Components 11.0.x. Шаблоны проектов взяты из Microsoft.AspNetCore.Components.WebAssembly.Templates и встроенного dotnet new blazor, поставляемого с SDK .NET 11. Там, где поведение различается между версиями, я указываю разницу между .NET 8, .NET 9, .NET 10 и .NET 11 прямо в тексте.

Что такое “Blazor United” в .NET 11 на самом деле

“Blazor United” не отдельная модель хостинга. Это было рабочее название, которым Microsoft пользовалась в течение цикла preview .NET 8 для того, что в итоге вышло как шаблон Blazor Web App. Шаблон объединяет четыре режима рендеринга в одном проекте:

Режим объявляется для каждого компонента: @rendermode InteractiveServer, @rendermode InteractiveWebAssembly или @rendermode InteractiveAuto. Один и тот же файл .razor может работать в любом из этих режимов, если не вызывает API, специфичные для конкретного режима (об этом ниже).

Blazor Server (автономный шаблон, dotnet new blazorserver) и Blazor WebAssembly (dotnet new blazorwasm) по-прежнему существуют в .NET 11, но рекомендация Microsoft с .NET 8 такова: предпочитайте унифицированный шаблон Blazor Web App, если у вас нет конкретной причины этого не делать.

Матрица возможностей

ВозможностьBlazor Server (автономный)Blazor WebAssembly (автономный)Blazor Web App / United (.NET 11)
Место рендерингасервербраузерпокомпонентно (Static, Server, WASM, Auto)
Начальный payload (холодный кеш)~50-80 КБ HTML~1,4 МБ WASM + сборки (R2R, .NET 11)~50-80 КБ HTML, WASM подгружается лениво
First Contentful Paint (LAN)~80-150 мс~600-900 мс~80-150 мс (Static / Server) ~600-900 мс (WASM-first)
Время до интерактивности после FCPдесятки мс (открытие WebSocket)сотни мс (загрузка WASM)зависит от режима рендеринга страницы
Требуется постоянный WebSocketда (SignalR)неттолько для компонентов Interactive Server
Работает офлайннетда (с service worker)да для компонентов WebAssembly, нет для Server
Прямой доступ к БД / файлам / секретамда (процесс сервера)нет (sandbox браузера)да в компонентах Server, нет в компонентах WASM
Поверхность API .NETполная серверная среда выполненияурезанное, безопасное для браузера подмножествообе, в зависимости от компонента
ОтладкаF5 в Visual Studio / Riderdevtools Chrome + отладчик WebAssembly в VSобе
Потолок масштабирования на серверограничен открытыми circuits (~5k на узел)неограничен (статика + API)ограничен только для страниц Interactive Server
Поддержка Native AOTнет (сервер по-прежнему JIT)частично через WASM AOTпо режиму рендеринга
Аутентификацияcookie + circuitOIDC / токен в браузереcookie для SSR/Server, токен для WASM
Статус в .NET 11поддерживается, не рекомендованный по умолчаниюподдерживается, не рекомендованный по умолчаниюрекомендованный по умолчанию

Последняя строка закрывает обсуждение для большинства новых приложений. Собственные шаблоны Microsoft, примеры из документации и туториалы начинают именно с шаблона Blazor Web App. Выбор только Server или только WebAssembly в 2026 году теперь является явным отклонением, которое требует обоснования.

Когда выбирать Blazor Server (автономный)

Автономный шаблон Blazor Server остаётся правильным выбором при одном из следующих ограничений:

Минимальный Program.cs для Blazor Server в .NET 11:

// .NET 11, C# 14, Microsoft.AspNetCore.Components.Server 11.0.x
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

var app = builder.Build();

app.UseStaticFiles();
app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

Обратите внимание: AddRazorComponents() плюс AddInteractiveServerComponents() — это API из .NET 8+. Старый AddServerSideBlazor() ещё работает, но проходит через слой совместимости и не задействует новую инфраструктуру режимов рендеринга. В любом greenfield-проекте используйте новые API.

Когда выбирать Blazor WebAssembly (автономный)

Берите автономный шаблон WebAssembly, когда:

Минимальный Program.cs для Blazor WebAssembly в .NET 11:

// .NET 11, C# 14, Microsoft.AspNetCore.Components.WebAssembly 11.0.x
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient
{
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});

await builder.Build().RunAsync();

В .NET 11 в среде выполнения WebAssembly многопоточность включена по умолчанию для новых проектов, если в .csproj поставить <WasmEnableThreads>true</WasmEnableThreads>. Это убирает одну из главных причин, по которой раньше отвергали Blazor WebAssembly: загрузка CPU больше не блокирует UI-поток.

Когда выбирать Blazor Web App (модель United)

Во всех остальных случаях. Унифицированный шаблон даёт один проект, в котором:

Такая композиция не повторяется больше нигде. Вы уходите от бинарного выбора “Server-приложение или WASM-приложение” к выбору по странице, ровно как Next.js позволяет смешивать ssr, static и client. Минимальный Program.cs для Blazor Web App в .NET 11:

// .NET 11, C# 14, Microsoft.AspNetCore.Components.Server 11.0.x +
// Microsoft.AspNetCore.Components.WebAssembly.Server 11.0.x
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

var app = builder.Build();

app.UseStaticFiles();
app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(BlazorApp.Client._Imports).Assembly);

app.Run();

Проект .Client, идущий в комплекте с шаблоном, — это место для компонентов, которым нужно работать на WebAssembly. Компоненты только для сервера остаются в хост-проекте. Компоненты Interactive Auto живут в .Client (потому что должны быть достижимы и со стороны WebAssembly).

Данные по холодному старту и размеру пакета

Цифры ниже получены из чистых dotnet new blazor, dotnet new blazorserver и dotnet new blazorwasm на SDK .NET 11 11.0.100-preview.4.26152.6, опубликованных через dotnet publish -c Release и поданных dotnet run. Измерено в Chrome 137 на MacBook Pro M2, с холодным кешем, при throttling “Fast 3G” в DevTools.

МетрикаBlazor ServerBlazor WebAssemblyBlazor Web App (Auto на главной)
Передано начального HTML8 КБ4 КБ8 КБ
Передано WebAssembly + сборок01,42 МБ (gzip)1,42 МБ (gzip, лениво)
Время до First Contentful Paint320 мс1850 мс340 мс
Время до интерактивности (кнопка counter)410 мс2300 мс440 мс (Server) / 2400 мс (передача в WASM)
Память после первой навигации7 МБ браузера38 МБ браузера9 МБ, затем 41 МБ после передачи

Blazor Web App в режиме Auto выигрывает у автономного WebAssembly по first paint в пять раз, потому что не ждёт пакет. Автономный Server он не выигрывает, потому что как только пакет WebAssembly догружается, память расходуется так же. Дело не в том, что Auto самый быстрый по какой-то одной метрике. Дело в том, что он никогда не самый медленный.

Для более глубокого взгляда на то, как SDK .NET 11 урезает пакет WASM, посмотрите новый шаблон Blazor WebWorker в .NET 11, который использует те же настройки trimmer.

Подводный камень, который выбирает за вас

Три вещи диктуют выбор независимо от предпочтений:

  1. Нельзя внедрить DbContext в компонент WebAssembly. Так же как и значение IConfiguration, содержащее секрет. И blob-клиент, использующий строку подключения. Браузер по дизайну — враждебная среда. Если ваш компонент должен читать БД напрямую, он обязан быть Server (или вам нужна бекенд-API, к которой обращается компонент WASM). Шаблон Blazor Web App показывает это сразу: добавьте @inject ApplicationDbContext Db в компонент .Client, и сборка упадёт с понятной ошибкой об отсутствующем внедрении зависимостей.

  2. Нельзя переключать @rendermode внутри границы режима рендеринга. Страница, рендерящаяся как Static Server, может содержать остров Interactive Server, а страница Interactive Server может содержать острова Interactive WebAssembly, но вложить интерактивность в интерактивность нельзя. На практике это означает: выбирайте самый низкий режим рендеринга, который годится для страницы, и поднимайтесь только на уровне островов.

  3. HTTPS, antiforgery и состояние аутентификации идут через cookies по умолчанию. Компоненты WebAssembly не видят эти cookies для cross-origin запросов. Если часть WebAssembly в Blazor Web App вызывает внешнюю API, поверх нужен поток токенов OIDC, а не только cookie хоста. Это самый частый камень преткновения при миграции приложения Blazor Server на шаблон Web App.

По части antiforgery поведение TempData в Blazor SSR в .NET 11 и руководство по совместной логике валидации разбирают практические паттерны.

Рекомендация ещё раз

Для нового Blazor-проекта на .NET 11 в 2026 году начинайте с dotnet new blazor (шаблона Blazor Web App) и назначайте режимы рендеринга для каждой страницы. Стоимость возможности опуститься до @rendermode StaticServer для маркетинговой страницы или подняться до @rendermode InteractiveWebAssembly для компонента с поддержкой офлайн почти нулевая по сравнению со стоимостью неправильного выбора автономного шаблона и последующей переписки. Выбирайте dotnet new blazorserver только при жёстком запрете на загрузку WebAssembly. Выбирайте dotnet new blazorwasm только если в целевом окружении нет среды выполнения .NET или если вы встраиваете фронтенд в MAUI Hybrid или Electron.

Если вы уже на Blazor Server и взвешиваете миграцию, цель почти всегда — шаблон Blazor Web App с большинством существующих страниц на @rendermode InteractiveServer. Это миграция с наименьшим риском: поведение страниц, которые переезжают, остаётся идентичным, а возможность инкрементально добавлять компоненты Static Server и Auto разблокирована.

Связанное

Источники

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Назад