Vorschau auf .NET 8.0: SPA-Inseln beim Server-side Rendering

Die fünfte Vorschauversion von .NET 8.0 führt die Projektvorlage "Blazor Web App" ein, was bei der Realisierung von serverseitigen Webanwendungen helfen kann.

In Pocket speichern vorlesen Druckansicht 6 Kommentare lesen

(Bild: Shutterstock)

Lesezeit: 8 Min.
Von
  • Dr. Holger Schwichtenberg
Inhaltsverzeichnis

.NET 8.0 Preview 5 führt mit der neuen Projektvorlage "Blazor Web App" eine Vorstufe für das geplante Blazor United ein. Dort können Entwickler und Entwicklerinnen einzelne Seiten einer serverseitigen Webanwendung als Single-Page-App mit Blazor Server realisieren. Blazor United ist der im Januar 2023 verkündete Plan des ASP.NET-Core-Entwicklungsteams, Blazor um reines Server-side Rendering zu erweitern und die bisherigen Architekturmodelle Blazor Server und Blazor WebAssembly so zu integrieren, dass aus Benutzerinnen- und Benutzersicht zur Laufzeit ein nahtloser Übergang der Rendering-Arten entsteht.

Das ASP.NET-Core-Entwicklungsteam hat diesen Plan zunächst auf Youtube angekündigt. Blazor Server-side Rendering gibt es seit .NET 8.0 Preview 3. Bisher mussten die Entwicklerinnen und Entwickler aber ein ASP.NET-Core-MVC- oder Razor-Pages-Projekt anlegen und einige Veränderungen manuell vornehmen. Das entfällt nun mit der Projektvorlage "Blazor Web App", die in .NET 8.0 Preview 5 sowie in Visual Studio 2022 17.7 Preview 2 zur Verfügung steht. Per Kommandozeile lässt sich ein derartiges Projekt folgendermaßen anlegen:

dotnet new blazor -o Projektname

In Visual Studio sehen Entwicklerteams bei installiertem .NET 8.0 Preview 5 SDK dann den in Abbildung 1 gezeigten Projektvorlageneintrag.

Projektvorlage für eine serverseitig gerenderte Blazor-Web-App in Visual Studio 2022 17.7 Preview 2 (Abb. 1).

(Bild: Microsoft)

Das Projekt enthält daraufhin alle notwendigen Startcode-Aufrufe wie AddRazorComponents() und MapRazorComponents<App>(), wobei auf die Startkomponente App.razor mit integriertem Routing verwiesen wird. Die einzelnen Komponenten (in der Projektvorlage MainLayout.razor, Index.razor, NavMenu.razor und ShowData.razor) müssen nicht mehr wie in Preview 3 und 4 die Schnittstelle IRazorComponentApplication implementieren. Die Komponente ShowData.razor besitzt den Zusatz:

@attribute [StreamRendering(true)]

Sie demonstriert damit das in Preview 4 eingeführte Streaming. Abbildung 2 zeigt, was ShowData.razor überträgt: Zunächst eine vollständige Seite, die auf dem Server gerendert wurde und die der Browser schon darstellt (hier mit einem Ladehinweis, siehe Zeilen 13 und 24, Abb. 2). Die verzögert eingehenden Ergebnisse aller asynchronen Operationen hängt ASP.NET Core in der gleichen HTML-Antwort noch an die Seite an (siehe <template> in Zeile 33 und 37, Abb. 2). Die JavaScript-Datei blazor.web.js, die am Ende der ursprünglichen Seite geladen wurde, baut die in den Tags <template> enthaltenen HTML-Fragmente dann in die ursprünglich dargestellte Seite ein, sodass Benutzer mit etwas Verzögerung die Wetterdatentabelle statt des Ladehinweises sehen.

Server Streaming bei Blazor SSR: Nach dem </html> kommen noch später eingehende Fragmente in der gleichen HTML-Antwort, die blazor.web.js in die Seite einsetzt (Abb. 2).

(Bild: Dr. Holger Schwichtenberg)

Es ist an der Kommandozeile aber bisher nicht in Visual Studio möglich, eine Projektvorlage zu erschaffen, die eine Integration zwischen Server-side Rendering und Blazor Server enthält:

dotnet new blazor --use-server -o Projektname

Entwickler und Entwicklerinnen sehen dann in der Startdatei die Aufrufkette:

builder.Services.AddRazorComponents().AddServerComponents();

und dann in der Komponente Counter.razor den Zusatz:

@attribute [RenderModeServer]

Das ist auch im Listing 1 zu sehen.

@page "/counter"
@attribute [RenderModeServer]
 
<PageTitle>Counter</PageTitle>
 
<h1>Counter</h1>
 
<p role="status">Current count: @currentCount</p>
 
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
 
@code {
    private int currentCount = 0;
 
    private void IncrementCount()
    {
        currentCount++;
    }
}


Listing 1: Counter.razor ist eine SPA-Insel innerhalb der serverseitig gerenderten Webanwendung

Das führt zu einer Single-Page-App innerhalb des Server-side Rendering: Diese Seite unter der URL /counter ist aus Sicht der Benutzerinnen und Benutzer interaktiv. Das heißt, der Zähler ändert sich beim Klick ohne Verzögerung durch Übertragung nur der Seitenänderungen über eine Websocket-Verbindung. Alle übrigen relativen Adressen in der Webanwendung rendern jedoch allein über HTTP (ohne Websockets) weiterhin serverseitig komplette Seiten. Abbildung 3 stellt die Rendering-Optionen (Blazor SSR ohne und mit Streaming) und Blazor Server in einem Schaubild dar. Komponenten in allen drei Varianten sind in einer Webanwendung möglich, sie können auf die gleiche Geschäftslogik zugreifen und einen gemeinsamen Anwendungszustand besitzen.

Innerhalb einer ASP.NET-Core-Webanwendung können Entwicklerinnen und Entwickler nun Server-side Rendering, Streaming und Blazor Server mischen (Abb. 3).

(Bild: Dr. Holger Schwichtenberg)

Bis das Ziel "Blazor United" erreicht ist, fehlen aber noch drei Punkte in .NET 8.0:

  • Integration von Blazor WebAssembly in gleicher Weise wie Blazor Server für einzelne Seiten.
  • Einfachere Verwendung von Blazor Server und Blazor WebAssembly für einzelne Komponenten innerhalb einer Komponente, die mit einer anderen Blazor-Variante erstellt wurde.
  • Nahtloser Übergang einer serverseitig gerenderten Seite zu Blazor Server und dann zu Blazor WebAssembly ("Hydrierung" der Seite).

Das seit .NET 8.0 Preview 4 für Blazor WebAssemby verfügbare WebCIL-Format ist nun der Standard in allen Webprojekten. Zudem hat Microsoft das Format so angepasst, dass Standard-WebAssembly-Module mit der Dateinamenserweiterung .wasm (in Preview 4 war es noch .webcil) entstehen. WebCIL mit WebAssembly-Modulen soll eine Blockierung von Blazor WebAssembly durch Firewalls und Anti-Viren-Software verhindern. Man kann WebCIL aber auch abschalten:

<WasmEnableWebcil>false</WasmEnableWebcil>

Wobei Microsoft im Blogeintrag offen lässt, in welchen Fällen dies geboten sein könnte. Bisher war der Standard, dass die Dateien die Erweiterung .dll aufwiesen.

Der Benachrichtigungsdienst ASP.NET Core SignalR (Praxisartikel in iX-Ausgabe 6/2023) kann jetzt nach kurzen Verbindungsabbrüchen die Verbindung automatisch nahtlos wiederherstellen. In .NET 8.0 Preview 5 funktioniert das nur mit .NET-Clients. Es gibt noch keinerlei Konfiguration dieser Fehlertoleranz, das soll aber später kommen. Der Client muss die Verbindung mit dem Zusatz UseAcks = true aufbauen:

var hubConnection = new HubConnectionBuilder()​

    .WithUrl("https://ServerName/Hub">",​

             options =>​

             {​

                options.UseAcks = true;​

             })​

    .Build();​

 ​

Von dieser Fehlertoleranz wird auch Blazor Server profitieren, weil dort ASP.NET Core SignalR für die Übertragung der Seitenänderungen zum Einsatz kommt. Die seit Preview 3 verfügbare Ahead-of-Time-Kompilierung für ASP.NET Core Minimal WebAPIs kann nun auch mit komplexen Objekten umgehen, die mit [AsParameters] annotiert sind.

Microsoft hat nun – wie auf der BUILD-Konferenz im Mai 2023 angekündigt – den Duende Identity Server aus seinen Projektvorlagen für React- und Angular-Projekte mit ASP.NET-Core-Backend verbannt. Das .NET-Entwicklungsteam sah sich dazu veranlasst, weil der in den Versionen 1 bis 4 als eine Open-Source-Software und ein Projekt der gemeinnützigen .NET Foundation verfügbare Identity Server mittlerweile ein kommerzielles Produkt ist. Nur noch Open-Source-Projekte sind von den Lizenzgebühren ausgenommen.

Die genannten Projektvorlagen von Microsoft basieren nun auf dem in ASP.NET Core integrierten Identity-System. Die Identitätsverwaltung ASP.NET Core Identity bietet seit .NET 8.0 Preview 4 neben der HTML-Benutzeroberfläche auch WebAPI-Endpunkte an. Entwicklerinnen und Entwickler, die weiterhin Identity Server nutzen wollen, verweist Microsoft an die Dokumentation von Duende. Zudem hat Microsoft in .NET 8.0 Preview 5 die Debugger-Ansicht einiger Klassen verbessert (Abb. 4).

Verbesserte Debugger-Ansicht in ASP.NET-Core-Projekten (Abb. 4).

(Bild: Microsoft)

In einem Blogeintrag listet Microsoft weitere Änderungen an .NET 8.0 außerhalb von ASP.NET Core und Blazor auf. Dazu gehören Vereinfachungen bei Metrics APIs. Das bisher als getrennte NuGet-Paket verfügbare Source Link zum Debugging im Sourcecode von NuGet-Paketen ist jetzt in das .NET SDK integriert. .NET 8.0 Preview 5 liefert eine Reihe neuer Code-Analyzer mit Refactoring-Funktionen, beispielsweise StartsWith() statt IndexOf() == 0 sowie Length, Count und IsEmpty statt Any().

Beim Erstellen einer Veröffentlichung einer .NET-Anwendung mit dotnet publish gibt es einen Breaking Change. Bei Angabe eines Runtime Identifiers der Option --runtime (alias -r) bei dotnet publish, zum Beispiel in

dotnet publish --runtime win-arm64

wurde bisher immer eine sogenannte Self-Contained Application (SCA) erstellt, die nicht nur die erstellte Anwendung selbst, sondern auch die dem Runtime Identifier entsprechende Laufzeitumgebung von .NET enthielt.

Das auszuliefernde Kompilat wurde dadurch sehr groß. Ab .NET 8.0 Preview 5 entsteht nun mit Angabe des Runtime Identifiers eine Anwendung, die nur auf der entsprechenden Plattform läuft, aber nicht automatisch auch die zugehörige Laufzeitumgebung enthält. Wenn Entwicklerinnen und Entwickler die Laufzeitumgebung bündeln wollen, ist dazu der Parameter --self-contained oder <SelfContained>true</SelfContained> in der Projektdatei explizit notwendig. Das gibt Entwicklerinnen und Entwicklern mehr Flexibilität. In diesem Zusammenhang gibt es auch Verhaltensänderungen für die Veröffentlichungsoptionen <PublishTrimmed> und <PublishReadyToRun>.

Zur Beschleunigung von .NET-Anwendungen setzt Microsoft nun im Standard auf die in .NET 6.0 eingeführte Dynamic Profile Guided Optimization (PGO). Entwicklerinnen und Entwickler, die das nicht wünschen, müssen fortan <TieredPGO>false</TieredPGO> in der Projektdatei angeben. PGO analysiert das Verhalten von Anwendungen (insbesondere die Reihenfolge der Nutzung von Programmteilen) und optimiert daraufhin den Just-in-Time-Compiler, sodass der beim Programmstart benötigte Programmcode bevorzugt übersetzt wird und die Anwendung schneller startet.

(fms)