Einleitung: Warum ist Caching in TypeScript notwendig?
Moderne Webanwendungen erfordern hohe Antwortgeschwindigkeiten und eine minimale Belastung der Datenbanken. Caching ist eine der effektivsten Methoden, dies zu erreichen. Im TypeScript- (und Node.js-) Ökosystem stehen Entwicklern drei Hauptansätze zur Verfügung: verteilte Systeme (Redis, Memcached) und integrierte Lösungen (In-Memory-Cache). In diesem Artikel analysieren wir jeden dieser Ansätze, geben praktische Beispiele in TypeScript und helfen Ihnen, die optimale Lösung für Ihr Projekt auszuwählen.
Caching ermöglicht es, häufig angefragte Daten in einem schnellen Speicher abzulegen und so wiederholte teure Operationen (Datenbankabfragen, Berechnungen, Aufrufe externer APIs) zu vermeiden. Eine richtige Caching-Strategie kann die Serverantwortzeit um das 10- bis 100-fache verkürzen.
1. Integriertes Caching in TypeScript (In-Memory)
Der einfachste Weg ist, Daten direkt im Speicher des Node.js-Prozesses zu speichern. Dafür sind keine externen Dienste erforderlich, was ideal für kleine Anwendungen oder Prototypen ist.
1.1. Verwendung von Map und WeakMap
Die integrierten JavaScript-Collections sind eine hervorragende Grundlage für einen einfachen Cache. Beispielimplementierung mit TTL (Time To Live):
type CacheEntry<T> = { value: T; expiresAt: number;};
class SimpleCache<T> { private store = new Map<string, CacheEntry<T>>();
set(key: string, value: T, ttlMs: number = 60000): void { this.store.set(key, { value, expiresAt: Date.now() + ttlMs, }); }
get(key: string): T | undefined { const entry = this.store.get(key); if (!entry) return undefined; if (Date.now() > entry.expiresAt) { this.store.delete(key); return undefined; } return entry.value; }
delete(key: string): boolean { return this.store.delete(key); }
clear(): void { this.store.clear(); }}
// Verwendungconst userCache = new SimpleCache<object>();userCache.set('user:1', { name: 'Alexej' }, 30000); // TTL 30 Sek.console.log(userCache.get('user:1'));1.2. Die Bibliothek node-cache
Für Produktionslösungen ist es besser, die bewährte Bibliothek node-cache zu verwenden. Sie bietet erweiterte Funktionen: automatische Bereinigung, Statistiken und Ereignisse.
import NodeCache from 'node-cache';
const myCache = new NodeCache({ stdTTL: 100, checkperiod: 120 });
// Objekt speichernconst success = myCache.set('myKey', { data: 'value' });if (success) console.log('Cache gespeichert');
// Lesenconst value = myCache.get('myKey');console.log(value); // { data: 'value' }
// Statistiken abrufenconst stats = myCache.getStats();console.log(`Treffer: ${stats.hits}, Fehlversuche: ${stats.misses}`);Vorteile: Einfachheit, keine Netzwerkverzögerung, keine Installation von Diensten erforderlich.
Nachteile: Cache geht bei Neustart der Anwendung verloren, nicht für verteilte Systeme geeignet.
2. Caching mit Redis in TypeScript
Redis ist die beliebteste Lösung für Caching in der Produktion. Es läuft als separater Server, unterstützt komplexe Datenstrukturen und ist resistent gegen Anwendungsneustarts.
2.1. Einbindung von ioredis
Die Bibliothek ioredis ist der De-facto-Standard für die Arbeit mit Redis in TypeScript. Sie unterstützt Clustering, Pub/Sub und Pipeline.
import Redis from 'ioredis';
const redis = new Redis({ host: 'localhost', port: 6379, retryStrategy: (times) => Math.min(times * 50, 2000),});
// Verbindung prüfenredis.on('connect', () => console.log('Mit Redis verbunden'));redis.on('error', (err) => console.error('Redis-Fehler:', err));2.2. Beispiel für Caching mit TTL
async function getCachedData(key: string): Promise<string | null> { const cached = await redis.get(key); if (cached) { console.log('Daten aus