Alles was du brauchst ist Express und JSX
Olivia Novak
Dev Intern · Leapcell

Serverseitiges Rendering in Express.js: Tiefgehender Vergleich von EJS und JSX (TypeScript-Praxis)
Node.js in Kombination mit Express.js bleibt eine goldene Kombination für die Erstellung effizienter Webanwendungen. Wenn wir dem Client dynamische HTML-Inhalte bereitstellen möchten, führt Express das Konzept einer „View Engine“ ein. Im Laufe der Jahre hat sich EJS (Embedded JavaScript) aufgrund seiner Einfachheit zu einer beliebten Wahl entwickelt. Seit dem Aufkommen von React hat JSX (JavaScript XML) mit seinem komponentenbasierten Ansatz für die UI-Konstruktion jedoch immensen Anklang bei Entwicklern gefunden, und seine Philosophie ist auch für das serverseitige Rendering voll anwendbar.
Dieser Artikel befasst sich damit, wie traditionelles EJS und modernes JSX für die Implementierung von serverseitigem Rendering (SSR) in einer mit TypeScript entwickelten Express.js-Anwendung verwendet werden. Wir vergleichen ihre Vor- und Nachteile, spezifische Implementierungsmethoden und diskutieren, wie die erstellte Anwendung bequem auf einer Cloud-Plattform bereitgestellt werden kann.
1. Einleitung: Serverseitiges Rendering und View Engines
Server-Side Rendering (SSR) ist eine Technologie, bei der eine vollständige HTML-Seite auf der Serverseite generiert und dann an den Client gesendet wird. Diese Methode kann die Ladezeit der ersten Ansicht effektiv verbessern und ist für die Suchmaschinenoptimierung (SEO) freundlich. Express.js vereinfacht den Prozess der Generierung dynamischer HTML-Inhalte durch seinen View Engine-Mechanismus.
Die Kernverantwortung einer View Engine besteht darin, Vorlagendateien mit dynamischen Daten zu kombinieren und sie in die endgültige HTML-Zeichenkette zu kompilieren. Express selbst bündelt keine spezifische View Engine; Entwickler können sie über app.set('view engine', 'engine_name') frei auswählen und konfigurieren.
2. EJS: Eine klassische Template-Engine
2.1 Überblick und Kernfunktionen von EJS
Wie der Name schon sagt, ermöglicht EJS (Embedded JavaScript) Entwicklern, JavaScript-Code in HTML-Vorlagen einzubetten. Für Entwickler, die mit traditionellen serverseitigen Skriptsprachen wie PHP und ASP vertraut sind, ist die EJS-Syntax sehr intuitiv und leicht verständlich.
Haupt-EJS-Tags:
<%= ... %>: Maskiert und gibt das Ergebnis eines JavaScript-Ausdrucks in HTML aus (verhindert XSS-Angriffe).<%- ... %>: Gibt das Ergebnis eines JavaScript-Ausdrucks ohne Maskierung in HTML aus (für Szenarien, in denen HTML-Inhalte bewusst eingebettet werden).<% ... %>: Wird verwendet, um JavaScript-Kontrollflussanweisungen auszuführen (wieif-Bedingungen,for-Schleifen usw.).<%# ... %>: Ein Kommentar-Tag, dessen Inhalt weder ausgeführt noch ausgegeben wird.<%- include('path/to/template') %>: Importiert und rendert eine andere EJS-Datei.
2.2 Verwenden von EJS in Express (TypeScript)
Installieren Sie zunächst die relevanten Abhängigkeiten:
npm install express ejs npm install --save-dev @types/express @types/ejs typescript nodemon ts-node
Ein grundlegendes tsconfig.json-Konfigurationsbeispiel:
{ "compilerOptions": { "target": "ES2022", // Ziel-JavaScript-Version "module": "commonjs", // Gemeinsames Modulsystem für die Node.js-Umgebung "rootDir": "./src", // TypeScript-Quellcodedateiverzeichnis "outDir": "./dist", // Kompilierte JavaScript-Datei-Ausgabeverzeichnis "esModuleInterop": true, // Ermöglicht Interoperabilität zwischen CommonJS und ES-Modulen "strict": true, // Aktiviert alle strikten Typüberprüfungsoptionen "skipLibCheck": true // Überspringt die Typüberprüfung von Deklarationsdateien }, "include": ["src/**/*"], // Gibt zu kompilierende Dateien an "exclude": ["node_modules"] // Gibt auszuschließende Dateien von der Kompilierung an }
Beispielcode für src/server.ts:
import express, { Request, Response } from 'express'; import path from 'path'; const app = express(); const port = process.env.PORT || 3001; // Portnummer kann angepasst werden // EJS als View Engine festlegen app.set('view engine', 'ejs'); // Verzeichnis der Vorlagendateien festlegen, z. B. 'src/views' app.set('views', path.join(__dirname, 'views')); app.get('/', (req: Request, res: Response) => { res.render('index', { // Rendert views/index.ejs title: 'EJS Demo-Seite', message: 'Willkommen auf der EJS-Vorlage, gesteuert von Express und TypeScript!', user: { name: 'Gast', isAdmin: false }, items: ['Apfel', 'Banane', 'Kirsche'] }); }); app.listen(port, () => { console.log(`EJS-Beispielserver läuft auf http://localhost:${port}`); });
Beispielvorlage für src/views/index.ejs:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><%= title %></title> <style> body { font-family: Arial, sans-serif; padding: 20px; } .user-greeting { color: blue; } .admin-panel { border: 1px solid red; padding: 10px; margin-top: 10px; } </style> </head> <body> <h1><%= message %></h1> <% if (user && user.name) { %> <p class="user-greeting">Hallo, <%= user.name %>!</p> <% if (user.isAdmin) { %> <div class="admin-panel">Willkommen, Administrator! Dies ist das Admin-Panel.</div> <% } else { %> <p>Sie haben derzeit normale Benutzerprivilegien.</p> <% } <% } %> <h2>Produktliste:</h2> <% if (items && items.length > 0) { %> <ul> <% items.forEach(function(item) { %> <li><%= item %></li> <% }); %> </ul> <% } else { %> <p>Keine Produkte verfügbar.</p> <% } %><%- include('partials/footer', { year: new Date().getFullYear() }) %> </body> </html>
src/views/partials/footer.ejs (für include):
<hr> <footer> <p>© <%= year %> Meine Webseite. Alle Rechte vorbehalten.</p> </footer>
2.3 Vorteile von EJS
- Einfach und intuitiv: Geringe Lernkurve, sehr freundlich für Entwickler mit HTML- und grundlegenden JavaScript-Kenntnissen.
- Hochflexibel: Ermöglicht die direkte Einbettung und Ausführung von beliebigen JavaScript-Codes in Vorlagen und bietet relative Freiheit bei der Handhabung komplexer Logik.
- Weit verbreitet und reifes Ökosystem: Als etablierte Template-Engine verfügt sie über eine große Anzahl bestehender Projekte und Community-Unterstützung.
2.4 Einschränkungen von EJS
- Mangelnde Typsicherheit: Selbst wenn das Hauptprojekt TypeScript verwendet, sind Daten, die an EJS-Vorlagen übergeben werden, innerhalb der Vorlage fast vom Typ
any. Dies erschwert die Erkennung von Problemen wie Tippfehlern bei Eigenschaftsnamen oder Abweichungen in der Datenstruktur während der Kompilierung und macht sie anfällig für Laufzeitfehler. - Herausforderungen bei Lesbarkeit und Wartbarkeit: Wenn Vorlagen übermäßige oder komplexe JavaScript-Logik einbetten, werden die HTML-Struktur und die Geschäftslogik stark gekoppelt, was den Code schwer lesbar und wartbar macht.
- Schwache Komponentisierungsfähigkeiten: Obwohl die
include-Direktive die Wiederverwendung von Vorlagenfragmenten ermöglicht, kämpft EJS im Vergleich zum deklarativen und zusammensetzbaren Komponentenmodell von JSX damit, große und komplexe Benutzeroberflächen zu erstellen. - Begrenzte IDE-Unterstützung: In
.ejs-Dateien können leistungsstarke TypeScript-Funktionen wie Typüberprüfung, intelligente Eingabeaufforderungen und Refactoring nicht vollständig genutzt werden.
3. JSX: Eine Syntaxerweiterung für die UI-Konstruktion
3.1 Überblick und Kernfunktionen von JSX (nicht nur für React)
JSX (JavaScript XML) ist eine Syntaxerweiterung für JavaScript, die es Entwicklern ermöglicht, HTML-ähnliche (oder XML-) Strukturen in JavaScript-Code zu schreiben. Obwohl JSX ursprünglich für React entwickelt wurde, ist es selbst eine unabhängige Spezifikation, die in jeden Zielcode kompiliert werden kann und nicht nur für React bestimmt ist. Auf der Serverseite können wir die deklarativen Features von JSX nutzen, um UI-Strukturen zu beschreiben und diese dann in HTML-Zeichenketten umzuwandeln.
JSX-Code kann nicht direkt von Browsern oder der Node.js-Umgebung ausgeführt werden; er muss über Tools wie Babel, den TypeScript-Compiler (tsc) oder esbuild in Standard-JavaScript-Funktionsaufrufe (wie React.createElement() oder benutzerdefinierte äquivalente Funktionen) transpiliert werden.
3.2 Warum JSX für serverseitiges Rendering wählen?
Für Entwickler, die mit modernen Frontend-Frameworks wie React und Vue vertraut sind, ist JSX (oder eine ähnliche Vorlagensyntax) die naheliegendste Wahl für den Aufbau komponentenbasierter UIs. Die Einführung in das serverseitige Rendering bietet zahlreiche Vorteile:
- Konsistenz zwischen Frontend und Backend: Ermöglicht ähnliches komponentenbasiertes Denken und Entwicklungsmuster auf Server- und Clientseite.
- Typsicherheit: In Kombination mit TypeScript können klare Typen für Komponenten-Props (Eigenschaften) definiert werden, was die durch die Typüberprüfung zur Kompilierungszeit erreichte Robustheit nutzt.
- Deklarativ und strukturiert: Der UI-Code ist deklarativer und hat eine klarere Struktur, was das Verständnis und die Wartung erleichtert.
- Wiederverwendbarkeit von Komponenten: Erleichtert die einfache Erstellung und Wiederverwendung von UI-Komponenten und verbessert die Entwicklungseffizienz.
3.3 Konfigurieren einer JSX-Umgebung in Express (TypeScript)
Um JSX für das serverseitige Rendering in Express zu verwenden, ist eine Konfiguration erforderlich. Wir verwenden react und react-dom/server, um JSX-Komponenten in HTML-Zeichenketten zu konvertieren. Beachten Sie, dass dies anders ist als bei clientseitigem React; hier nutzen wir nur seine JSX-Parsing- und Zeichenkettengenerierungsfähigkeiten, ohne virtuelle DOM-Operationen oder clientseitige Lebenszyklen einzubeziehen.
3.3.1 Installation der notwendigen Abhängigkeiten
npm install express react react-dom npm install --save-dev @types/express @types/react @types/react-dom typescript nodemon ts-node esbuild esbuild-register
esbuild ist ein extrem schnelles Tool zum Bündeln und Transpilieren von JavaScript/TypeScript. esbuild-register kann .ts- und .tsx-Dateien während der Entwicklung sofort transpilieren, was es sehr praktisch macht. In der Produktion wird in der Regel eine Vorabkompilierung empfohlen.
3.3.2 Konfigurieren von tsconfig.json
Damit der TypeScript-Compiler korrekt mit JSX-Syntax umgeht, ist die folgende Konfiguration in tsconfig.json erforderlich:
{ "compilerOptions": { // ... andere Konfigurationen bleiben unverändert ... "jsx": "react-jsx", // Empfohlen für die neue JSX-Transformation, keine manuelle Importierung von React erforderlich // "jsx": "react", // Legacy-JSX-Transformation, erfordert die Importierung von React in jeder .tsx-Datei: import React from 'react'; "esModuleInterop": true, "module": "commonjs", "outDir": "./dist", "rootDir": "./src", "strict": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules"] }
Die Option `

