__dirname is not defined - La solution Node.js ultime

Xavier Moreau .

23 mai 2026

Logo Node.js sur fond vert. Le texte "node" est stylisé avec des formes hexagonales. Le "js" est dans un hexagone blanc. Erreur courante : __dirname is not defined.

Le message __dirname is not defined apparaît presque toujours quand un fichier Node.js n’est plus exécuté en CommonJS, mais en modules ES ou dans un runtime qui ne fournit pas les variables classiques de Node. Pour un backend ou une API, le vrai enjeu n’est pas seulement de faire disparaître l’erreur, mais de choisir le bon repère de chemin selon le contexte: répertoire du module, dossier courant du processus ou URL du fichier. Je vais aller droit au point avec les causes, les corrections propres et les cas où il vaut mieux changer de stratégie plutôt que bricoler autour du problème.

Ce qu’il faut savoir avant de toucher au code

  • __dirname n’existe qu’en CommonJS dans Node.js, pas dans les ES modules.
  • La correction la plus propre en ESM consiste à partir de import.meta.url, puis à convertir vers un chemin fichier si nécessaire.
  • Si vous cherchez le dossier de travail lancé par le process, utilisez process.cwd() et non le dossier du module.
  • Sur les versions récentes de Node.js, import.meta.dirname simplifie le cas ESM pour les modules locaux.
  • Le problème revient souvent après un passage de require vers import, ou quand un bundler change le contexte d’exécution.

Un développeur quitte le ciel gris de Node.js + CommonJS pour rejoindre la fête sous le soleil avec les bundlers, navigateurs et Node.js + ESM. Le __dirname n'est pas défini ici.

Pourquoi cette erreur apparaît dans un projet Node.js moderne

La cause est assez simple: Node.js réserve __dirname au monde CommonJS. La documentation Node.js le dit clairement: ces variables ressemblent à des globals, mais elles n’existent que dans la portée des modules CommonJS. Dès qu’un fichier est traité comme un module ES, cette variable disparaît, et l’accès direct déclenche l’erreur.

Dans la pratique, je vois ce cas arriver après trois changements très courants: l’ajout de "type": "module" dans package.json, le passage d’un fichier de .cjs à .js ou .mjs, ou la migration d’un vieux code backend vers une syntaxe import/export. Le piège, c’est qu’un projet peut compiler sans problème et échouer seulement au moment où une route API ou un script de démarrage essaie de lire un fichier local. Le symptôme arrive donc tard, souvent en préproduction, ce qui rend le diagnostic plus irritant qu’il ne devrait l’être.

Il faut aussi garder un autre point en tête: ce nom de variable n’a rien de standard en JavaScript du navigateur. Si votre code tourne dans un runtime orienté web, ou si un bundler l’exécute dans un contexte différent de Node, la variable ne sera pas disponible non plus. Autrement dit, le problème n’est pas seulement « une variable manquante », c’est surtout un mauvais modèle d’exécution pour le code qui l’utilise.

La correction propre en modules ES

Quand votre projet est en ESM, la solution la plus robuste consiste à repartir de import.meta.url, puis à convertir cette URL en chemin fichier si vous avez besoin d’une chaîne de caractères. C’est la voie la plus compatible, et elle reste claire pour n’importe qui lit le code plus tard.

La version compatible avec la plupart des environnements

import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

Ce bloc recrée l’équivalent du dossier du module. Je l’utilise surtout quand je dois construire des chemins relatifs vers des fichiers de configuration, des templates, des schémas JSON ou des fixtures de test. Il est simple, explicite, et il évite les contorsions autour du répertoire courant du process.

Lire aussi : Closures PHP - Maîtrisez-les pour un backend lisible et évolutif

La version la plus courte sur Node récent

const moduleDir = import.meta.dirname;

Sur les versions récentes de Node.js, c’est plus direct. Je le recommande quand vous ciblez clairement un runtime moderne et que vous savez que le code ne sera pas transposé dans un environnement plus ancien. Le gain est réel, mais il y a une limite: cette propriété n’a de sens que pour les modules locaux servis depuis le système de fichiers. Pour des cas plus complexes, je préfère encore garder la version explicite avec fileURLToPath(), parce qu’elle laisse moins de place aux surprises.

Pour charger un fichier voisin, la forme URL peut même être plus nette qu’une concaténation de chaînes:

import { readFile } from 'node:fs/promises';

const schema = await readFile(new URL('./schema.json', import.meta.url), 'utf8');

Dans une API, cette approche évite de dépendre du répertoire de lancement du serveur. Elle colle au fichier qui consomme la ressource, ce qui est généralement ce qu’on veut vraiment. C’est aussi pour cela que je distingue toujours « chemin du module » et « chemin de lancement » avant de corriger quoi que ce soit.

Ne confondez pas le dossier du module et le dossier courant

Une partie des correctifs ratés viennent d’une confusion très banale: __dirname pointe vers le répertoire du fichier courant, alors que process.cwd() renvoie le dossier depuis lequel le process a été lancé. Ces deux valeurs peuvent être identiques en local, puis diverger dès qu’on passe par Docker, PM2, un worker, des tests automatisés ou un déploiement serverless.

Besoin réel Bonne référence Pourquoi
Lire un fichier placé à côté du module import.meta.dirname ou new URL(..., import.meta.url) Le chemin suit le fichier, pas la commande de démarrage
Résoudre un chemin relatif au lancement de l’application process.cwd() Utile pour une CLI, un script d’administration ou une configuration passée par l’opérateur
Garder un comportement historique dans un ancien backend CommonJS __dirname Le runtime l’expose encore naturellement dans ce mode
Construire un chemin absolu à partir d’un point de départ connu path.resolve(...) Pratique pour normaliser un chemin, surtout quand l’entrée est partielle

Je vois souvent des correctifs du style path.resolve(process.cwd(), 'config.json') remplacés trop vite par un équivalent censé être « comme __dirname ». Ce n’est pas la même chose. Si votre fichier doit rester stable quelle que soit la manière dont le serveur est lancé, fiez-vous au module, pas au dossier courant.

À l’inverse, si votre logique dépend volontairement de l’endroit depuis lequel l’outil a été lancé, alors process.cwd() est le bon outil. C’est une nuance simple, mais elle évite beaucoup de bugs discrets dans les backends et les API qui manipulent des fichiers de configuration.

Les pièges de configuration qui déclenchent le bug

Le plus souvent, le problème n’est pas dans la ligne qui plante, mais dans la configuration qui a changé en amont. Voici les cas que je vérifie en premier quand je débloque ce genre d’erreur:

  • "type": "module" dans package.json transforme les fichiers .js en ES modules.
  • L’extension .mjs force aussi le mode ESM, même si le reste du projet reste ancien.
  • Un mélange de CommonJS et d’ESM peut rendre le comportement difficile à lire, surtout si une partie du code vient d’un package tiers.
  • Les bundlers et transpileurs peuvent réécrire la structure des modules, ce qui change la disponibilité des variables implicites.
  • Les environnements d’exécution alternatifs ne reproduisent pas toujours le même modèle que Node pur.

Dans une base existante, je conseille de ne pas corriger ce symptôme fichier par fichier sans stratégie. Quand on mélange plusieurs conventions, on crée vite une dette technique plus coûteuse que l’erreur elle-même. Si le projet doit rester en CommonJS pour l’instant, gardez ce choix explicitement. Si la migration vers ESM est actée, faites-la complètement sur le périmètre concerné, puis adaptez les chemins en conséquence.

Autre détail qui compte: si vous avez juste besoin de require dans un fichier ESM, Node permet de construire un équivalent via module.createRequire(). Mais cela ne règle pas le dossier courant, seulement l’accès à l’écosystème CommonJS. Il ne faut pas confondre les deux problèmes.

Une méthode simple pour fiabiliser un backend sans casser les chemins

Quand je corrige ce type d’incident sur une API, je procède presque toujours de la même manière. D’abord, j’identifie le mode de module réel du fichier. Ensuite, je décide si le code doit s’ancrer sur le module, sur le process, ou sur une URL relative. Enfin, je centralise ce choix dans un helper plutôt que de répéter des conversions partout.

  1. Vérifier si le fichier tourne en CommonJS ou en ESM.
  2. Déterminer si le besoin porte sur le répertoire du module ou sur le dossier de lancement.
  3. Choisir un seul mécanisme de chemin pour le projet ou pour le sous-module concerné.
  4. Tester le comportement depuis un démarrage local, un test automatisé et, si possible, un conteneur.
  5. Éviter les remplacements globaux à l’aveugle, surtout dans les chemins de fichiers sensibles.

Si je dois standardiser cela dans une base de code moderne, je crée souvent un petit utilitaire partagé:

import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

export const moduleDir =
  typeof import.meta.dirname === 'string'
    ? import.meta.dirname
    : dirname(fileURLToPath(import.meta.url));

Ce helper me donne un point d’ancrage unique. Il est utile quand le projet doit tourner sur plusieurs versions de Node, ou quand une partie de l’équipe n’a pas encore migré tous les fichiers au même rythme. Ce n’est pas le code le plus court, mais c’est souvent le plus honnête pour un backend qui doit survivre au temps.

Ce que je recommande pour une API Node.js en 2026

Si je devais résumer la bonne pratique en une règle simple, je dirais ceci: gardez le module comme référence quand vous lisez des fichiers voisins, et gardez le process seulement quand vous cherchez un point de départ opérationnel. C’est cette distinction qui évite la majorité des erreurs de chemin dans les projets backend et API.

  • Pour du nouveau code, partez en ESM si le projet le justifie, puis utilisez import.meta.dirname ou le couple fileURLToPath + dirname.
  • Pour des ressources locales, préférez new URL('./fichier', import.meta.url) quand c’est possible.
  • Pour une configuration liée au lancement du serveur, utilisez process.cwd() en connaissance de cause.
  • Pour un projet legacy déjà stable, ne migrez pas CommonJS vers ESM juste pour faire disparaître l’erreur sans autre bénéfice.

Au fond, ce message d’erreur révèle surtout un choix de conception. Une fois ce choix clarifié, le correctif devient simple, et votre code gagne en lisibilité au lieu de s’appuyer sur un contournement fragile. C’est exactement le genre de détail qui fait la différence entre un backend qui fonctionne sur ma machine et une API qui reste fiable en production.

Questions fréquentes

Cette erreur survient lorsque vous utilisez `__dirname` dans un fichier traité comme un module ES (ESM) plutôt que comme un module CommonJS. Node.js réserve `__dirname` uniquement aux modules CommonJS. Un changement de configuration ou une migration vers `import`/`export` peut en être la cause.
La solution la plus robuste en ESM est d'utiliser `import.meta.url`, puis de le convertir en chemin de fichier si nécessaire. Vous pouvez utiliser `fileURLToPath` de `node:url` et `dirname` de `node:path` pour recréer l'équivalent de `__dirname`.
`__dirname` pointe vers le répertoire du fichier en cours d'exécution, tandis que `process.cwd()` renvoie le répertoire depuis lequel le processus Node.js a été lancé. Ils peuvent différer selon l'environnement (Docker, tests, etc.). Il est crucial de choisir la bonne référence selon le besoin.
`import.meta.dirname` est une propriété plus récente de Node.js qui simplifie l'obtention du répertoire du module en ESM. Utilisez-la si vous ciblez un environnement Node.js moderne. Pour une compatibilité maximale ou des cas complexes, la combinaison `fileURLToPath` et `dirname` est préférable.
Non. Si votre projet fonctionne bien en CommonJS, il n'est pas toujours nécessaire de migrer. L'erreur indique un conflit de mode de module. Si vous restez en CommonJS, `__dirname` fonctionnera. Si vous migrez, assurez-vous d'adapter tous les chemins en conséquence.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

__dirname is not defined __dirname not defined node.js __dirname is not defined en esm remplacer __dirname par import.meta.url process.cwd() vs __dirname __dirname dans les modules es
Autor Xavier Moreau
Xavier Moreau
Je m'appelle Xavier Moreau et je cumule 14 ans d'expérience dans le développement web, avec un accent particulier sur JavaScript, le backend, le NoSQL et la sécurité. Mon intérêt pour ces domaines a émergé dès mes débuts dans la programmation, où j'ai découvert la puissance des technologies web et leur capacité à transformer des idées en réalité. J'aime expliquer des concepts complexes de manière accessible, en aidant les lecteurs à naviguer dans les défis techniques qu'ils rencontrent. Au fil des ans, j'ai développé une expertise solide en vérifiant mes sources, en comparant les informations et en simplifiant des sujets parfois ardus. Je m'efforce toujours de fournir des contenus utiles, précis et à jour, en suivant les tendances du secteur et en organisant mes connaissances de manière claire. Mon objectif est d'accompagner les passionnés et les professionnels du développement web dans leur quête de compréhension et d'innovation.

Commentaires (0)

Ajouter un commentaire