Поделиться через


Предварительный рендеринг компонентов ASP.NET Core Razor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске смотрите версию .NET 9 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске смотрите версию .NET 9 этой статьи.

В этой статье описываются Razor сценарии предварительной подготовки компонентов для компонентов, отрисованных на сервере, в Blazor Web Appприложениях и Blazor Server приложениях.

Предварительная отрисовка — это процесс статической отрисовки содержимого страницы с сервера для доставки HTML в браузер как можно быстрее. После быстрого отображения предварительно созданного содержимого пользователю интерактивное содержимое с активными обработчиками событий будет отображаться, заменив содержимое, которое было отрисовывается ранее. Предварительная подготовка также может улучшить оптимизацию поисковой системы (SEO), отрисовав содержимое для первоначального HTTP-ответа, используемого поисковыми системами для вычисления ранжирования страниц.

Предварительная подготовка включена по умолчанию для интерактивных компонентов.

Внутренняя навигация с интерактивной маршрутизацией не использует предварительную отрисовку, так как страница уже интерактивна. Дополнительные сведения см. в разделе "Статическая и интерактивная маршрутизация " и "Интерактивная маршрутизация" и "Предварительная подготовка".

OnAfterRender{Async} События жизненного цикла компонентов не вызываются при предварительной подготовке, только после интерактивной отрисовки компонента.

Отключение предварительной подготовки

Предварительная отрисовка может усложнить приложение, так как компоненты приложения Razor должны отображаться дважды: один раз для предварительной подготовки и один раз для настройки интерактивности. Если компоненты настроены для запуска в WebAssembly, необходимо также разработать компоненты, чтобы они могли работать как с сервера, так и с клиента.

Чтобы отключить пререндеринг для экземпляра компонента, передайте флаг prerender со значением false в режим отрисовки:

  • <... @rendermode="new InteractiveServerRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveAutoRenderMode(prerender: false)" />

Чтобы отключить предварительную отрисовку в определении компонента, выполните следующие действия.

  • @rendermode @(new InteractiveServerRenderMode(prerender: false))
  • @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
  • @rendermode @(new InteractiveAutoRenderMode(prerender: false))

Чтобы отключить предварительную отрисовку для всего приложения, укажите режим отрисовки на самом высоком уровне интерактивного компонента в иерархии компонентов приложения, которая не является корневым компонентом.

Для приложений, основанных на шаблоне проекта Blazor Web App, режим отрисовки, примененный ко всему приложению, указывается там, где компонент Routes используется в компоненте App (Components/App.razor). В следующем примере для режима отрисовки приложения устанавливается интерактивный сервер с отключенным предварительным рендерингом.

<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Кроме того, отключите предварительную отрисовку компонента HeadOutlet в компоненте:App

<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Создание корневого компонента, такого как компонент App, который взаимодействует с директивой @rendermode в верхней части файла определения корневого компонента (.razor), не поддерживается. Следовательно, предварительный рендеринг не может быть отключен непосредственно с помощью компонента App.

Отключение предварительной подготовки с помощью описанных выше методов действует только для режимов отрисовки верхнего уровня. Если родительский компонент задает режим рендеринга, параметры предварительного рендеринга дочерних элементов игнорируются.

Поддерживать предварительно рендеренное состояние

Без сохранения предварительно отрисованного состояния все состояния, которые использовались во время предварительной отрисовки, теряются и должны быть созданы заново при полной загрузке приложения. Если какое-либо состояние создается асинхронно, пользовательский интерфейс может мерцать при замене предварительно отрендеренного интерфейса во время перерисовки компонента. Инструкции по сохранении состояния во время предварительной подготовки см. в разделе ASP.NET Сохраняемость предварительно созданного состояния CoreBlazor.

Не удается выполнить клиентские службы во время пререндеринга

Если предварительное визуализирование не отключено для компонента или для приложения, компонент в проекте .Client предварительно визуализируется на сервере. Поскольку сервер не имеет доступа к зарегистрированным клиентским Blazor службам, невозможно внедрить эти службы в компонент без получения ошибки, вызванной отсутствием службы во время предварительного рендеринга.

Например, рассмотрим следующий компонент в проекте в с глобальной интерактивной сборкой WebAssembly или интерактивным автосбором . Компонент пытается использовать IWebAssemblyHostEnvironment для получения имени среды.

@page "/"
@inject IWebAssemblyHostEnvironment Environment

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    Environment: @Environment.Environment
</p>

Ошибка времени компиляции не возникает, но во время предварительной подготовки возникает ошибка среды выполнения:

Не удается указать значение свойства "Среда" в типе BlazorSample.Client.Pages..Home Зарегистрированная служба типа Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment отсутствует.

Эта ошибка возникает из-за того, что компонент должен компилировать и выполнять на сервере во время предварительной подготовки, но IWebAssemblyHostEnvironment не является зарегистрированной службой на сервере.

Рассмотрим любой из следующих подходов к решению этого сценария:

Регистрация службы на сервере в дополнение к клиенту

Если служба поддерживает выполнение сервера, зарегистрируйте службу на сервере в дополнение к клиенту, чтобы она была доступна во время предварительной подготовки. Пример этого сценария см. в руководстве по HttpClient службам во Blazor Web App внешних веб-API статьи "Вызов веб-API ".

Внедрение службы, которую приложение может использовать во время предварительной подготовки

В некоторых случаях приложение может использовать службу на сервере во время предварительной подготовки и другой службы на клиенте.

Например, следующий код получает среду приложения независимо от того, выполняется ли код на сервере или на клиенте, внедряя IHostEnvironment из Microsoft.Extensions.Hosting.Abstractions пакета NuGet:

private string? environmentName;

public Home(IHostEnvironment? serverEnvironment = null, 
    IWebAssemblyHostEnvironment? wasmEnvironment = null)
{
    environmentName = serverEnvironment?.EnvironmentName;
    environmentName ??= wasmEnvironment?.Environment;
}

Однако этот подход добавляет дополнительную зависимость к клиентскому проекту, который не нужен.

Сделать службу необязательной

Сделайте сервис необязательным, если он не требуется во время предварительного рендеринга, используя любой из следующих подходов.

В следующем примере используется внедрение конструктора IWebAssemblyHostEnvironment:

private string? environmentName;

public Home(IWebAssemblyHostEnvironment? env = null)
{
    environmentName = env?.Environment;
}

В качестве альтернативы можно добавить IServiceProvider, чтобы получить службу, если она будет доступна.

@page "/"
@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IServiceProvider Services

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    <b>Environment:</b> @environmentName
</p>

@code {
    private string? environmentName;

    protected override void OnInitialized()
    {
        if (Services.GetService<IWebAssemblyHostEnvironment>() is { } env)
        {
            environmentName = env.Environment;
        }
    }
}

Создание абстракции службы

Если на сервере требуется другая реализация службы, создайте абстракцию службы и создайте реализации для службы на сервере и клиентских проектах. Зарегистрируйте службы в каждом проекте. Внедрите абстракцию пользовательской службы в компоненты в тех местах, где это требуется. Затем компонент зависит исключительно от абстракции пользовательской службы.

В этом случае IWebAssemblyHostEnvironmentможно повторно использовать существующий интерфейс вместо создания нового:

ServerHostEnvironment.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.AspNetCore.Components;

public class ServerHostEnvironment(IWebHostEnvironment env, NavigationManager nav) : 
    IWebAssemblyHostEnvironment
{
    public string Environment => env.EnvironmentName;
    public string BaseAddress => nav.BaseUri;
}

В файле проекта Program сервера зарегистрируйте службу:

builder.Services.TryAddScoped<IWebAssemblyHostEnvironment, ServerHostEnvironment>();

На этом этапе IWebAssemblyHostEnvironment служба может быть внедрена в интерактивный компонент WebAssembly или Auto, который также предопределен с сервера.

Отключение предварительной подготовки для компонента

Отключите предварительный рендеринг компонента или отключите его для всего приложения. Дополнительные сведения см. в разделе "Отключение предварительной загрузки".