Vorabrendern von ASP.NET Core Razor-Komponenten

In diesem Artikel werden Szenarien zum Vorabrendern von Razor-Komponenten für serverseitige gerenderte Komponenten in Blazor-Web Apps erläutert.

Prerendering ist der Prozess des anfänglichen Renderns von Seiteninhalten auf dem Server, ohne Ereignishandler für gerenderte Steuerelemente zu aktivieren. Der Server gibt die HTML-Benutzeroberfläche der Seite so schnell wie möglich als Reaktion auf die anfängliche Anforderung aus, wodurch die Anwendung für Benutzer besser reagiert. Prerendering kann auch die Suchmaschinenoptimierung (SEO) verbessern, indem Inhalte für die erste HTTP-Antwort gerendert werden, die Suchmaschinen zur Berechnung des Seitenrangs verwenden.

Beibehalten des vorab gerenderten Zustands

Ohne Beibehaltung des vorab gerenderten Zustands geht der Zustand verloren, der während des Vorabrenderings verwendet wird, und muss neu erstellt werden, wenn die App vollständig geladen ist. Wenn ein Zustand asynchron erstellt wird, flackert die Benutzeroberfläche möglicherweise, da die vorab gerenderte Benutzeroberfläche ersetzt wird, wenn die Komponente erneut gerendert wird.

Betrachten Sie die folgende PrerenderedCounter1-Zählerkomponente. Die Komponente legt während des Vorabrenderns in die OnInitialized-Lebenszyklusmethode einen anfänglichen zufälligen Zählerwert fest. Nachdem die SignalR-Verbindung mit dem Client hergestellt wurde, wird die Komponente erneut ausgeführt, und der anfängliche Zählerwert wird ersetzt, wenn OnInitialized ein zweites Mal ausgeführt wird.

PrerenderedCounter1.razor:

@page "/prerendered-counter-1"
@rendermode @(new InteractiveServerRenderMode(prerender: true))
@inject ILogger<PrerenderedCounter1> Logger

<PageTitle>Prerendered Counter 1</PageTitle>

<h1>Prerendered Counter 1</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount;

    protected override void OnInitialized()
    {
        currentCount = Random.Shared.Next(100);
        Logger.LogInformation("currentCount set to {Count}", currentCount);
    }

    private void IncrementCount()
    {
        currentCount++;
    }
}

Führen Sie die App aus, und prüfen Sie die Protokollierung aus der Komponente. Es folgt eine Beispielausgabe.

Hinweis

Wenn die App interaktives (erweitertes) Routing verwendet und die Seite über eine interne Navigation erreicht wird, findet das Vorabrendering nicht statt. Daher müssen Sie die gesamte Seite für die PrerenderedCounter1-Komponente neu laden, um die folgende Ausgabe anzuzeigen.

info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 41
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 92

Die erste protokollierte Anzahl erfolgt während des Vorabrenderings. Die Anzahl wird erneut festgelegt, nachdem die Komponente neu gerendert wurde. Die Benutzeroberfläche flackert auch, wenn die Anzahl von 41 auf 92 aktualisiert wird.

Um den Anfangswert des Zählers während des Vorabrenderings beizubehalten, unterstützt Blazor das Beibehalten des Zustands auf einer vorab gerenderten Seite mithilfe des PersistentComponentState-Diensts (und für Komponenten, die in Seiten oder Ansichten von Razor Pages- oder MVC-Apps eingebettet sind, das Hilfsprogramm für Persist Component State Tag Helper).

Entscheiden Sie, welcher Zustand mithilfe des PersistentComponentState-Diensts beibehalten werden soll, um den vorab gerenderten Zustand beizubehalten. Mit PersistentComponentState.RegisterOnPersisting wird zum Beibehalten des Komponentenzustands ein Rückruf registriert, bevor die App angehalten wird. Der Zustand wird abgerufen, wenn die App fortgesetzt wird.

Das folgende Beispiel veranschaulicht das allgemeine Muster:

  • Der {TYPE}-Platzhalter stellt den Typ der zu speichernden Daten dar.
  • Der {TOKEN}-Platzhalter ist eine Zustandsbezeichnerzeichenfolge. Erwägen Sie die Verwendung von nameof({VARIABLE}), wobei der Platzhalter {VARIABLE} der Name der Variable ist, die den Zustand enthält. Die Verwendung von nameof() für den Zustandsbezeichner verhindert die Verwendung einer Zeichenfolge mit Anführungszeichen.
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
    private {TYPE} data;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistData);

        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

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

Im folgenden Beispiel für Zählerkomponenten wird der Zählerzustand während des Vorabrenderns beibehalten und der Zustand abgerufen, um die Komponente zu initialisieren.

PrerenderedCounter2.razor:

@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState

<PageTitle>Prerendered Counter 2</PageTitle>

<h1>Prerendered Counter 2</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override void OnInitialized()
    {
        persistingSubscription =
            ApplicationState.RegisterOnPersisting(PersistCount);

        if (!ApplicationState.TryTakeFromJson<int>(
            nameof(currentCount), out var restoredCount))
        {
            currentCount = Random.Shared.Next(100);
            Logger.LogInformation("currentCount set to {Count}", currentCount);
        }
        else
        {
            currentCount = restoredCount!;
            Logger.LogInformation("currentCount restored to {Count}", currentCount);
        }
    }

    private Task PersistCount()
    {
        ApplicationState.PersistAsJson(nameof(currentCount), currentCount);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose() => persistingSubscription.Dispose();

    private void IncrementCount()
    {
        currentCount++;
    }
}

Wenn die Komponente ausgeführt wird, wird currentCount sie während des Vorabrenderns nur einmal festgelegt. Der Wert wird wiederhergestellt, wenn die Komponente erneut gerendert wird. Es folgt eine Beispielausgabe.

Hinweis

Wenn die App interaktives Routing verwendet und die Seite über eine interne Navigation erreicht wird, findet das Vorabrendering nicht statt. Daher müssen Sie die gesamte Seite für die PrerenderedCounter2-Komponente neu laden, um die folgende Ausgabe anzuzeigen.

info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount restored to 96

Durch das Initialisieren von Komponenten mit demselben Zustand, der während des Prerenderings verwendet wird, werden teure Initialisierungsschritte nur einmal ausgeführt. Die gerenderte Benutzeroberfläche entspricht auch der vorab gerenderten Benutzeroberfläche, sodass im Browser kein Flimmern auftritt.

In Seiten und Ansichten eingebettete Komponenten (Razor Pages/MVC)

Für Komponenten, die in eine Seite oder Ansicht von Razor Pages- oder einer MVC-App eingebettet sind, müssen Sie das Hilfsprogramm Persist Component State Tag Helper mit dem <persist-component-state /> HTML-Tag innerhalb des schließenden </body> Tags des App-Layouts hinzufügen. Dies ist nur für Razor Pages- und MVC-Apps erforderlich. Weitere Informationen finden Sie unter Persist Component State Tag Helper in ASP.NET Core.

Pages/Shared/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

Interaktives Routing und Vorabrendering

Die interne Navigation für interaktives Routing umfasst nicht das Anfordern neuer Seiteninhalte vom Server. Daher findet das Vorabrendering nicht für interne Seitenanforderungen statt.

Der PersistentComponentState-Dienst funktioniert nur beim Laden der ersten Seite und nicht bei erweiterten Seitennavigationsereignissen. Wenn die App eine vollständige (nicht erweiterte) Navigation zu einer Seite ausführt, die den permanenten Komponentenstatus verwendet, wird der permanente Status für die App verfügbar gemacht, wenn sie interaktiv wird. Wenn jedoch bereits eine interaktive Schaltung eingerichtet wurde und eine erweiterte Navigation zu einer Seite ausgeführt wird, die den permanenten Komponentenstatus rendert, wird dieser Status nicht in der vorhandenen Schaltung verfügbar gemacht. Dem PersistentComponentState-Dienst ist keine erweiterte Navigation bekannt, und es gibt keinen Mechanismus zum Bereitstellen von Statusupdates für Komponenten, die bereits ausgeführt werden.

Anleitungen zum Vorabrendering

Anleitungen zum Vorabrendering sind in der Blazor-Dokumentation nach Themen organisiert. Unter den folgenden Links finden Sie alle Anleitungen zum Vorabrendering in der Dokumentation nach Themen geordnet: