Introduction : pourquoi la mise en cache en TypeScript ?
Les applications web modernes nécessitent une vitesse de réponse élevée et une charge minimale sur les bases de données. La mise en cache est l’un des moyens les plus efficaces d’y parvenir. Dans l’écosystème TypeScript (et Node.js), trois approches principales sont disponibles pour les développeurs : les systèmes distribués (Redis, Memcached) et les solutions intégrées (cache en mémoire). Dans cet article, nous analyserons chacune d’elles, fournirons des exemples pratiques en TypeScript et vous aiderons à choisir l’option optimale pour votre projet.
La mise en cache permet de stocker les données fréquemment demandées dans un stockage rapide, évitant ainsi des opérations coûteuses répétées (requêtes à la base de données, calculs, appels à des API externes). Une stratégie de mise en cache appropriée peut réduire le temps de réponse du serveur de 10 à 100 fois.
1. Mise en cache intégrée en TypeScript (en mémoire)
La méthode la plus simple consiste à stocker les données directement dans la mémoire du processus Node.js. Cela ne nécessite aucun service externe, ce qui est idéal pour les petites applications ou les prototypes.
1.1. Utilisation de Map et WeakMap
Les collections intégrées de JavaScript constituent une excellente base pour un cache simple. Exemple d’implémentation avec 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(); }}
// Utilisationconst userCache = new SimpleCache<object>();userCache.set('user:1', { name: 'Alexeï' }, 30000); // TTL 30 secconsole.log(userCache.get('user:1'));1.2. Bibliothèque node-cache
Pour les solutions de production, il est préférable d’utiliser la bibliothèque éprouvée node-cache. Elle offre des fonctionnalités avancées : nettoyage automatique, statistiques et événements.
import NodeCache from 'node-cache';
const myCache = new NodeCache({ stdTTL: 100, checkperiod: 120 });
// Sauvegarder un objetconst success = myCache.set('myKey', { data: 'value' });if (success) console.log('Cache sauvegardé');
// Lireconst value = myCache.get('myKey');console.log(value); // { data: 'value' }
// Obtenir les statistiquesconst stats = myCache.getStats();console.log(`Succès : ${stats.hits}, Échecs : ${stats.misses}`);Avantages : simplicité, latence réseau nulle, ne nécessite pas d’installation de services.
Inconvénients : le cache est perdu lors du redémarrage de l’application, ne convient pas aux systèmes distribués.
2. Mise en cache avec Redis en TypeScript
Redis est la solution de mise en cache la plus populaire en production. Il fonctionne comme un serveur séparé, prend en charge des structures de données complexes et résiste aux redémarrages de l’application.
2.1. Connexion avec ioredis
La bibliothèque ioredis est la norme de facto pour travailler avec Redis depuis TypeScript. Elle prend en charge le clustering, Pub/Sub et Pipeline.
import Redis from 'ioredis';
const redis = new Redis({ host: 'localhost', port: 6379, retryStrategy: (times) => Math.min(times * 50, 2000),});
// Vérification de la connexionredis.on('connect', () => console.log('Connecté à Redis'));redis.on('error', (err) => console.error('Erreur Redis :', err));2.2. Exemple de mise en cache avec TTL
async function getCachedData(key: string): Promise<string | null> { const cached = await redis.get(key); if (cached) { console.log('Données du