Comment optimiser l'utilisation de la mémoire

À mesure que les applications grandissent et deviennent plus riches en fonctionnalités, elles peuvent demander plus de ressources lors du développement local ou de la création de builds de production.

Explorons quelques stratégies et techniques pour optimiser la mémoire et résoudre les problèmes courants de mémoire dans Next.js.

Réduire le nombre de dépendances

Les applications avec un grand nombre de dépendances utiliseront plus de mémoire.

L'Analyseur de bundle (Bundle Analyzer) peut vous aider à identifier les dépendances volumineuses dans votre application qui pourraient être supprimées pour améliorer les performances et l'utilisation de la mémoire.

Essayer experimental.webpackMemoryOptimizations

À partir de la version v15.0.0, vous pouvez ajouter experimental.webpackMemoryOptimizations: true à votre fichier next.config.js pour modifier le comportement de Webpack afin de réduire l'utilisation maximale de la mémoire, mais cela peut légèrement augmenter les temps de compilation.

Bon à savoir : Cette fonctionnalité est actuellement expérimentale pour être testée sur plus de projets, mais elle est considérée comme à faible risque.

Exécuter next build avec --experimental-debug-memory-usage

À partir de la version 14.2.0, vous pouvez exécuter next build --experimental-debug-memory-usage pour lancer la build dans un mode où Next.js affichera en continu des informations sur l'utilisation de la mémoire tout au long de la build, comme l'utilisation du tas (heap) et les statistiques de garbage collection. Des instantanés du tas (heap snapshots) seront également pris automatiquement lorsque l'utilisation de la mémoire approchera la limite configurée.

Bon à savoir : Cette fonctionnalité n'est pas compatible avec l'option de worker de build Webpack qui est activée automatiquement sauf si vous avez une configuration Webpack personnalisée.

Enregistrer un profil de tas (heap)

Pour rechercher des problèmes de mémoire, vous pouvez enregistrer un profil de tas depuis Node.js et le charger dans Chrome DevTools pour identifier les sources potentielles de fuites de mémoire.

Dans votre terminal, passez le flag --heap-prof à Node.js lors du lancement de votre build Next.js :

node --heap-prof node_modules/next/dist/bin/next build

À la fin de la build, un fichier .heapprofile sera créé par Node.js.

Dans Chrome DevTools, vous pouvez ouvrir l'onglet Mémoire et cliquer sur le bouton "Charger le profil" pour visualiser le fichier.

Analyser un instantané du tas (heap)

Vous pouvez utiliser un outil d'inspection pour analyser l'utilisation de la mémoire de l'application.

Lors de l'exécution des commandes next build ou next dev, ajoutez NODE_OPTIONS=--inspect au début de la commande. Cela exposera l'agent d'inspection sur le port par défaut. Si vous souhaitez interrompre avant que tout code utilisateur ne démarre, vous pouvez passer --inspect-brk à la place. Pendant que le processus est en cours d'exécution, vous pouvez utiliser un outil comme Chrome DevTools pour vous connecter au port de débogage afin d'enregistrer et d'analyser un instantané du tas pour voir quelle mémoire est retenue.

À partir de la version 14.2.0, vous pouvez également exécuter next build avec le flag --experimental-debug-memory-usage pour faciliter la prise d'instantanés du tas.

Lors de l'exécution dans ce mode, vous pouvez envoyer un signal SIGUSR2 au processus à tout moment, et le processus prendra un instantané du tas.

L'instantané du tas sera enregistré dans la racine du projet de l'application Next.js et pourra être chargé dans n'importe quel analyseur de tas, comme Chrome DevTools, pour voir quelle mémoire est retenue. Ce mode n'est pas encore compatible avec les workers de build Webpack.

Consultez comment enregistrer et analyser des instantanés du tas (heap snapshots) pour plus d'informations.

Worker de build Webpack

Le worker de build Webpack vous permet d'exécuter les compilations Webpack dans un worker Node.js séparé, ce qui réduira l'utilisation de la mémoire de votre application pendant les builds.

Cette option est activée par défaut si votre application n'a pas de configuration Webpack personnalisée à partir de la version v14.1.0.

Si vous utilisez une version plus ancienne de Next.js ou si vous avez une configuration Webpack personnalisée, vous pouvez activer cette option en définissant experimental.webpackBuildWorker: true dans votre next.config.js.

Bon à savoir : Cette fonctionnalité peut ne pas être compatible avec tous les plugins Webpack personnalisés.

Désactiver le cache Webpack

Le cache Webpack sauvegarde les modules Webpack générés en mémoire et/ou sur disque pour améliorer la vitesse des builds. Cela peut aider pour les performances, mais cela augmentera également l'utilisation de la mémoire de votre application pour stocker les données en cache.

Vous pouvez désactiver ce comportement en ajoutant une configuration Webpack personnalisée à votre application :

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (
    config,
    { buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
  ) => {
    if (config.cache && !dev) {
      config.cache = Object.freeze({
        type: 'memory',
      })
    }
    // Important : retourner la configuration modifiée
    return config
  },
}

export default nextConfig

Désactiver l'analyse statique

La vérification des types (typechecking) et le linting peuvent nécessiter beaucoup de mémoire, surtout dans les grands projets. Cependant, la plupart des projets ont un runner CI dédié qui gère déjà ces tâches. Lorsque la build produit des problèmes de mémoire insuffisante pendant l'étape "Linting et vérification des types", vous pouvez désactiver ces tâches pendant les builds :

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    // Attention : Cela permet aux builds de production de se terminer avec succès même si
    // votre projet contient des erreurs ESLint.
    ignoreDuringBuilds: true,
  },
  typescript: {
    // !! ATTENTION !!
    // Permet dangereusement aux builds de production de se terminer avec succès même si
    // votre projet contient des erreurs de type.
    // !! ATTENTION !!
    ignoreBuildErrors: true,
  },
}

export default nextConfig

Gardez à l'esprit que cela peut produire des déploiements défectueux en raison d'erreurs de type ou de problèmes de linting. Nous recommandons fortement de ne promouvoir les builds en production qu'après que l'analyse statique ait été complétée. Si vous déployez sur Vercel, vous pouvez consulter le guide pour les déploiements de staging pour apprendre comment promouvoir les builds en production après que les tâches personnalisées aient réussi.

Désactiver les source maps

La génération de source maps consomme de la mémoire supplémentaire pendant le processus de build.

Vous pouvez désactiver la génération de source maps en ajoutant productionBrowserSourceMaps: false et experimental.serverSourceMaps: false à votre configuration Next.js.

Bon à savoir : Certains plugins peuvent activer les source maps et peuvent nécessiter une configuration personnalisée pour les désactiver.

Problèmes de mémoire avec Edge

Next.js v14.1.3 a corrigé un problème de mémoire lors de l'utilisation du runtime Edge. Veuillez mettre à jour vers cette version (ou une version ultérieure) pour voir si cela résout votre problème.

Préchargement des entrées

Lorsque le serveur Next.js démarre, il précharge les modules JavaScript de chaque page en mémoire, plutôt qu'au moment de la requête.

Cette optimisation permet des temps de réponse plus rapides, en échange d'une empreinte mémoire initiale plus importante.

Pour désactiver cette optimisation, définissez le flag experimental.preloadEntriesOnStart sur false.

import type { NextConfig } from 'next'

const config: NextConfig = {
  experimental: {
    preloadEntriesOnStart: false,
  },
}

export default config

Next.js ne décharge pas ces modules JavaScript, ce qui signifie que même avec cette optimisation désactivée, l'empreinte mémoire de votre serveur Next.js finira par être la même si toutes les pages sont finalement demandées.