Alles, was Sie brauchen, sind Express und JSX
Olivia Novak
Dev Intern · Leapcell

Serverseitiges Rendering in Express.js: Ein detaillierter Vergleich von EJS und JSX (TypeScript-Übung)
Node.js in Kombination mit Express.js bleibt eine ideale Kombination für die Entwicklung effizienter Webanwendungen. Wenn wir dem Client dynamische HTML-Inhalte bereitstellen müssen, 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 zur UI-Erstellung jedoch enorme Beliebtheit bei Entwicklern gewonnen, und seine Philosophie ist auch auf serverseitiges Rendering voll anwendbar.
Dieser Artikel befasst sich eingehend mit der Verwendung von traditionellem EJS und modernem JSX zur Implementierung des serverseitigen Renderings (SSR) in einer mit TypeScript entwickelten Express.js-Anwendung. Wir werden ihre Vor- und Nachteile, spezifische Implementierungsmethoden vergleichen und erörtern, wie die erstellte Anwendung bequem auf einer Cloud-Plattform bereitgestellt werden kann.
1. Einführung: Serverseitiges Rendering und View Engines
Serverseitiges 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 Ladegeschwindigkeit des ersten Bildschirms effektiv verbessern und ist suchmaschinenfreundlich (SEO). Express.js vereinfacht den Prozess der Generierung dynamischen HTML-Codes durch seinen View-Engine-Mechanismus.
Die Kernaufgabe einer View Engine besteht darin, Vorlagendateien mit dynamischen Daten zu kombinieren und in die endgültige HTML-Zeichenkette zu kompilieren. Express selbst bündelt keine bestimmte View Engine; Entwickler können diese frei auswählen und über app.set('view engine', 'engine_name')
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.
Hauptsächlich 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 absichtlich eingebettet werden).<% ... %>
: Wird verwendet, um JavaScript-Kontrollflussanweisungen auszuführen (z. B.if
-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", // Common Module System für die Node.js-Umgebung "rootDir": "./src", // TypeScript-Quelldateiverzeichnis "outDir": "./dist", // Ausgabeverzeichnis für kompilierte JavaScript-Dateien "esModuleInterop": true, // Ermöglicht die Interoperabilität zwischen CommonJS- und ES-Modulen "strict": true, // Aktiviert alle strikten Typprüfungsoptionen "skipLibCheck": true // Überspringt die Typprüfung von Deklarationsdateien }, "include": ["src/**/*"], // Gibt die zu kompilierenden Dateien an "exclude": ["node_modules"] // Gibt die von der Kompilierung auszuschließenden Dateien 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 // Legen Sie EJS als View Engine fest app.set('view engine', 'ejs'); // Legen Sie das Vorlagendateiverzeichnis fest, 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-Demoseite', message: 'Willkommen zur EJS-Vorlage, die von Express und TypeScript gesteuert wird!', 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 reguläre Benutzerrechte.</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 Website. Alle Rechte vorbehalten.</p> </footer>
2.3 Vorteile von EJS
- Einfach und Intuitiv: Sanfte Lernkurve, sehr freundlich für Entwickler mit HTML- und grundlegenden JavaScript-Kenntnissen.
- Hohe Flexibilität: Ermöglicht das direkte Einbetten und Ausführen von beliebigem JavaScript-Code in Vorlagen und bietet relative Freiheit bei der Handhabung komplexer Logik.
- Weit verbreitetes und ausgereiftes Ökosystem: Als etablierte Template Engine verfügt es über eine große Anzahl bestehender Projekte und Community-Support.
2.4 Einschränkungen von EJS
- Fehlende Typsicherheit: Selbst wenn das Hauptprojekt TypeScript verwendet, sind an EJS-Vorlagen übergebene Daten innerhalb der Vorlage fast immer vom Typ
any
. Dies erschwert das Erkennen von Problemen wie Tippfehlern bei Eigenschaftsnamen oder Datenstruktur-Fehlpaarungen während der Kompilierung, was zu Laufzeitfehlern führt. - Herausforderungen bei Lesbarkeit und Wartbarkeit: Wenn Vorlagen übermäßige oder komplexe JavaScript-Logik einbetten, werden HTML-Struktur und Geschäftslogik stark gekoppelt, was den Code schwer lesbar und wartbar macht.
- Schwache Komponentenfähigkeit: Obwohl die
include
-Direktive die Wiederverwendung von Vorlagenfragmenten ermöglicht, hat EJS im Vergleich zum deklarativen und zusammensetzbaren Komponentenmodell von JSX Schwierigkeiten, große und komplexe UIs zu erstellen. - Eingeschränkte IDE-Unterstützung: In
.ejs
-Dateien können leistungsstarke Funktionen von TypeScript wie Typprüfung, intelligente Eingabeaufforderungen und Refactoring nicht vollständig genutzt werden.
3. JSX: Eine Syntaxerweiterung für die UI-Erstellung
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 es ursprünglich für React entwickelt wurde, ist JSX selbst eine unabhängige Spezifikation, die in jeden Zielcode kompiliert werden kann und nicht auf React beschränkt ist. Auf der Serverseite können wir die deklarativen Funktionen von JSX nutzen, um UI-Strukturen zu beschreiben und diese dann in HTML-Zeichenketten zu konvertieren.
JSX-Code kann nicht direkt von Browsern oder der Node.js-Umgebung ausgeführt werden; er muss mithilfe von Tools wie Babel, dem TypeScript-Compiler (tsc
) oder esbuild
in Standard-JavaScript-Funktionsaufrufe (z. B. React.createElement()
oder benutzerdefinierte äquivalente Funktionen) transpiliert werden.
3.2 Warum JSX für serverseitiges Rendering wählen?
Für Entwickler, die an moderne Front-End-Frameworks wie React und Vue gewöhnt sind, ist JSX (oder eine ähnliche Vorlagensyntax) eine natürliche Wahl für die Erstellung komponentenbasierter UIs. Die Einführung in das serverseitige Rendering bietet zahlreiche Vorteile:
- Konsistenz zwischen Frontend und Backend: Ermöglicht ähnliches komponentenbasiertes Design-Denken und Entwicklungsmuster sowohl auf der Server- als auch auf der Clientseite.
- Typsicherheit: In Kombination mit TypeScript ermöglicht es die Definition klarer Typen für Komponenten-Props (Eigenschaften), wodurch die Robustheit der Kompilierzeit-Typprüfung genutzt werden kann.
- Deklarativ und strukturiert: UI-Code ist deklarativer, mit klarerer Struktur, was das Verständnis und die Wartung erleichtert.
- Komponenten-Wiederverwendung: 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 gewisse Konfiguration erforderlich. Wir verwenden react
und react-dom/server
, um JSX-Komponenten in HTML-Zeichenketten zu konvertieren. Beachten Sie, dass dies sich vom clientseitigen React unterscheidet; hier verwenden wir nur die JSX-Analyse- und Zeichenketten-Generierungsfunktionen, ohne virtuelle DOM-Operationen oder clientseitige Lebenszyklen einzubeziehen.
3.3.1 Installieren der erforderlichen 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 blitzschnelles JavaScript/TypeScript-Bündelungs- und Transpilierungs-Tool. esbuild-register
kann .ts
- und .tsx
-Dateien während der Entwicklung sofort transpilieren, was es sehr komfortabel macht. In der Produktion wird in der Regel eine Vorkompilierung empfohlen.
3.3.2 Konfigurieren von tsconfig.json
Um sicherzustellen, dass der TypeScript-Compiler die JSX-Syntax korrekt verarbeitet, ist die folgende Konfiguration in tsconfig.json
erforderlich:
{ "compilerOptions": { // ... Andere Konfigurationen bleiben unverändert ... "jsx": "react-jsx", // Empfohlen für die neue JSX-Transformation, kein manueller Import von React erforderlich // "jsx": "react", // Legacy JSX-Transformation, erfordert den Import 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 `