Next.js consomme trop de mémoire : comment diagnostiquer

La RAM monte, le site ralentit, puis le processus redémarre. Avant d’augmenter la limite du heap, il faut savoir ce qui a grossi et à quel moment. Le problème peut venir du build, d’un cache, de réponses volumineuses ou d’objets qui restent accessibles.

Ce guide propose un diagnostic reproductible. Il ne suppose pas qu’une consommation élevée est une fuite, et il sépare les observations du serveur de celles de l’onglet navigateur.

Identifier le processus et la phase

Commencez par relever les versions Node et Next.js, la commande lancée et les limites du conteneur ou du service. Un serveur next dev garde des outils de compilation qui ne décrivent pas next start. Un arrêt pendant next build suit encore un autre chemin.

Regardez le journal avant le redémarrage. Une erreur du heap V8 et un processus tué par la limite mémoire du système sont deux signaux différents. Conservez l’heure, le PID et la charge en cours. Le graphique du VPS ne permet pas, à lui seul, d’attribuer la mémoire à Next.js.

Terminal
node --version
npm ls next react react-dom
ps -eo pid,ppid,rss,comm --sort=-rss

Comparer heap, RSS et mémoire du service

process.memoryUsage() expose notamment rss, heapUsed, heapTotal, external et arrayBuffers en octets. Appelez-le dans le processus applicatif que vous cherchez à comprendre, par exemple dans une instrumentation privée. Un node -e lancé à côté mesurerait uniquement ce nouveau processus.

Si heapUsed baisse après les cycles de collecte alors que le RSS reste élevé, cela ne prouve pas une fuite JavaScript. Les allocations natives, les buffers et le comportement de l’allocateur méritent aussi d’être examinés. Pour plusieurs processus, ajoutez une observation du groupe complet. Évitez un endpoint public exposant vos diagnostics.

instrumentation.node.js
const timer = setInterval(() => {
  const { rss, heapUsed, external } = process.memoryUsage();
  console.log(JSON.stringify({
    event: "memory-sample",
    pid: process.pid,
    rss, heapUsed, external,
    at: new Date().toISOString()
  }));
}, 10000);
timer.unref();

Rejouer un parcours qui fait croître la mémoire

Choisissez une route suspecte et répétez un lot de requêtes identique, puis laissez le serveur revenir au calme. Notez les valeurs après chaque lot. Une hausse initiale qui atteint un plateau peut correspondre au chargement de modules ou à un cache borné.

Une progression persistante après des lots comparables demande une investigation plus précise. Cherchez les collections globales alimentées par utilisateur, les caches sans expiration, les abonnements non libérés et les gros objets conservés par des closures. Testez aussi les requêtes annulées et les connexions interrompues si votre application utilise le streaming.

Traiter séparément les problèmes de compilation

Si l’échec se produit pendant le build, relevez l’étape précise : transformation, vérification TypeScript ou prérendu. Une page générée pour des milliers de paramètres ne pose pas le même problème qu’une dépendance énorme chargée par le compilateur.

La documentation Next.js décrit un mode expérimental de diagnostic mémoire de build, avec des limites selon le worker et le moteur de compilation. Vérifiez son applicabilité à votre version avant utilisation. Réduisez un import ou un lot de génération dans une branche, puis comparez le résultat. Augmenter --max-old-space-size ne crée pas de RAM et peut rapprocher le processus de la limite du VPS.

Utiliser un snapshot sur une instance de diagnostic

Un heap snapshot permet d’examiner les objets et leurs chemins de rétention. Comparez des captures prises à des étapes comparables d’un scénario, puis cherchez ce qui reste retenu après les lots suivants. Le volume seul est moins utile que la référence qui empêche la libération.

La capture peut suspendre le processus et demander beaucoup de mémoire supplémentaire. Utilisez une instance de diagnostic avec des données adaptées. Un snapshot peut contenir des informations applicatives sensibles ; gardez-le privé. Le port de débogage ne doit pas être ouvert publiquement.

Vérifier la correction avec la même charge

Après correction, rejouez le scénario, les annulations et une période de repos. Comparez la mémoire, les erreurs et les temps de réponse. Une baisse du heap accompagnée d’un effondrement du débit peut révéler un compromis de collecte plutôt qu’une amélioration globale.

Pour évaluer un autre moteur comme PRNext, conservez cette méthode et les mêmes routes. Changer de moteur ne corrige pas automatiquement un cache applicatif non borné. Commencez par vérifier la compatibilité, puis mesurez le coût du service entier.

Construire un benchmark SSR avec validation du contenu

Préparer un essai de PRNext sur une copie du projet

Sources et lectures complémentaires

Retour au blog