Book Monkey v5: Server-Side Rendering mit Angular 17
21.11.2023
Mit Angular 17 wurde der Build-Prozess für Server-Side Rendering (SSR) und Pre-Rendering grundlegend überarbeitet. In diesem Blogpost stellen wir vor, welche Unterschiede für das Beispielprojekt "BookMonkey" aus dem Angular-Buch relevant sind.
Der neue Application Builder
Mit Angular 17 wurde Server-Side Rendering noch tiefer in Angular integriert.
Schon beim Anlegen eines neuen Projekts mit ng new
können wir die Unterstützung für SSR sofort aktivieren.
Um den gesamten Build-Prozess zu harmonisieren, wurde außerdem der neue Application Builder eingeführt: Er vereint den Build für Browser und Server, sodass beide Schritte mit einem Befehl gemeinsam erledigt werden können.
Der neue Builder ist in neuen Projekten mit Angular 17 automatisch aktiv. Wir haben darüber bereits im Blogpost zum Angular-Release 17 berichtet.
SSR einrichten
Um Server-Side Rendering und Pre-Rendering in einer bestehenden Anwendung einzurichten, wird ab sofort das neue Paket @angular/ssr
verwendet.
Das bisherige Paket @nguniversal/express-engine
, das wir im Buch verwenden, wird nicht mehr genutzt.
ng add @angular/ssr
Unterschiede in den generierten Dateien
Nachdem die Einrichtung von SSR abgeschlossen ist, können wir die Änderungen an den Dateien nachvollziehen. Wir haben im Buch ausführlich beschrieben, welche Aspekte dabei wichtig sind. Der grundlegende Ablauf ist noch immer der gleiche – der Code sieht jedoch anders aus. Wir haben den Code im GitHub-Repo für den BookMonkey aktualisiert.
Skripte in der Datei package.json
Bisher wurden in der Datei package.json
mehrere Skripte hinzugefügt, mit denen die Builder für SSR und Pre-Rendering angestoßen werden können.
Da der Application Builder nun alle diese Aspekte übernimmt, wird nur noch ein einziges Skript hinzugefügt.
Es ist dafür verantwortlich, die SSR-Anwendung nach dem Build zu starten.
{
// ...
"scripts": {
// ...
"serve:ssr:book-monkey": "node dist/book-monkey/server/server.mjs"
}
}
Der gesamte Build wird nun mit dem gewohnten Befehl ng build
angestoßen und beinhaltet auch den Teil für den Server und die statisch generierten HTML-Dateien für Pre-Rendering.
Das Verhalten können wir in der Datei angular.json
konfigurieren.
Konfiguration in der Datei angular.json
In der Datei angular.json
wird der Application Builder konfiguriert.
Bisher waren hier einzelne Build Targets für SSR und Pre-Rendering notwendig. Der neue Builder vereint alle Teile unter dem Target build
.
Das bedeutet auch, dass nur noch der Befehl ng build
notwendig ist, um den gesamten Build auszuführen. Dabei wird die Anwendung also nicht nur für den Browser gebaut, sondern es wird auch der Node.js-Server für SSR generiert, und die statischen HTML-Dateien aus den Routen werden mithilfe von Pre-Rendering erzeugt.
SSR und Pre-Rendering können in der angular.json
separat aktiviert und gesteuert werden.
Die folgenden neuen Einträge sind hier nach der Einrichtung zu finden:
{
"projects": {
"book-monkey": {
"architect": {
"build": {
// ...
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "server.ts"
}
}
}
}
}
}
Pre-Rendering konfigurieren
Im Buch haben wir gezeigt, wie wir die Liste der Routen für Pre-Rendering manuell übergeben können.
Ab sofort muss diese Liste in einer Datei abgelegt und in der angular.json
referenziert werden.
Anstatt dem Wert true
können wir für prerender
das folgende Konfigurationsobjekt übergeben:
"prerender": {
"discoverRoutes": false,
"routesFile": "routes.txt"
},
Die Datei routes.txt
liegt im Root-Verzeichnis des Projekts und hat den folgenden Inhalt.
Bisher hatten wir diese Liste in der angular.json
definiert.
/
/home
/books
/books/9783864909467
/books/9783864907791
/books/9783864906466
/books/9783864903571
Sonstige Änderungen
- Die Datei
server.ts
beinhaltet weiterhin einen Express-Server für den SSR-Prozess. Hier wird nun allerdings die neueCommonEngine
aus dem Paket@angular/ssr
verwendet. Der Aufbau wird dadurch vereinfacht. - Im
AppModule
wird automatisch der EintragprovideClientHydration()
unterproviders
hinzugefügt. Damit wird die Client-Side Hydration aktiviert. Wir haben darüber im Blogpost zu Angular 16 berichtet. - Die Datei
app.server.module.ts
wurde umbenannt zuapp.module.server.ts
. Der Inhalt ist weiterhin derselbe.
Bestehendes Projekt updaten
Wenn Sie ein bestehendes Projekt auf Angular 17 aktualisieren, sorgen die Migrationsskripte hinter ng update
dafür, dass automatisch das neue Paket @angular/ssr
verwendet wird.
Dabei wird allerdings nicht automatisch der neue Application Builder eingerichtet, sondern es werden weiterhin die bisherigen Builder für SSR und Pre-Rendering genutzt, die in das Paket @angular-devkit/build-angular
umgezogen wurden.
❯ Replace usages of '@nguniversal/builders' with '@angular-devkit/build-angular'.
UPDATE angular.json (5182 bytes)
UPDATE package.json (1903 bytes)
Migration completed (2 files modified).
❯ Replace usages of '@nguniversal/' packages with '@angular/ssr'.
RENAME server.ts => server.ts.bak
CREATE server.ts (2206 bytes)
UPDATE package.json (1887 bytes)
✔ Packages installed successfully.
Migration completed (2 files modified).
Wenn Sie von hier aus den Application Builder nutzen möchten, ist eine manuelle Migration notwendig. Die grundlegenden Schritte haben wir im Blogpost zu Angular 17 beschrieben.
Fazit
Die Einrichtung und Konfiguration von SSR und Pre-Rendering funktioniert mit Angular 17 und dem neuen Application Builder anders als zuvor. Für bestehende Projekte ist damit zwar etwas Aufwand zur Migration nötig – wir begrüßen allerdings sehr, dass der Build-Prozess harmonisiert wird und das Thema SSR mehr in den Fokus rückt.
Sie können weiterhin auch die bestehenden Builder nutzen, die aus dem Paket @nguniversal/express-engine
nach @angular-devkit/build-angular
verschoben wurden.
Dennoch empfehlen wir Ihnen den Umstieg auf den Application Builder, um alle Vorteile und Optimierungen sofort zu nutzen.
An den konzeptionellen Grundlagen zu SSR, die wir im Buch ausführlich beschrieben haben, ändert sich darüber hinaus nichts. Der Ablauf ist noch immer der gleiche – nur die Umsetzung im Code hat sich mit Angular 17 geändert.
Titelbild: Photo by Dmitriy Demidov on Unsplash
Suggestions? Feedback? Bugs? Please fork/edit this page on Github.