166 votes

Alternative pour __dirname dans le noeud lors de l'utilisation du drapeau --experimental-modules

J'utilise le drapeau --experimental-modules lors de l'exécution de mon application node afin d'utiliser les modules ES6.

Cependant, lorsque j'utilise ce drapeau, la métavariable __dirname n'est pas disponible. Existe-t-il un autre moyen d'obtenir la même chaîne de caractères que celle stockée dans le fichier __dirname qui est compatible avec ce mode ?

0 votes

Voici une solution pour obtenir __dirname travaillant en ES6, jetez un coup d'œil

268voto

GOTO 0 Points 3049

Depuis Node.js 10.12, il existe une alternative qui ne nécessite pas la création de plusieurs fichiers et qui gère les caractères spéciaux dans les noms de fichiers sur toutes les plateformes :

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

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

1 votes

Cool, mais comment configurer l'IDE WebStrom pour qu'il comprenne cette syntaxe ?

0 votes

@ViES Je ne sais pas, mais j'ai trouvé cette question qui est déjà corrigé, donc cela devrait être possible avec la dernière version je pense.

3 votes

Quels sont les avantages de cette solution par rapport à path.dirname(process.argv[1]) ?

29voto

Mike Brant Points 39322

Pour Node 10.12 +...

En supposant que vous travaillez à partir d'un module, cette solution devrait fonctionner, et vous donne également le support de __filename également

import path from 'path';
import { fileURLToPath } from 'url';

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

Ce qui est bien, c'est que vous n'êtes qu'à deux lignes de code de la prise en charge de require() pour les modules CommonJS. Pour cela, il faut ajouter :

import { createRequireFromPath } from 'module';
const require = createRequireFromPath(__filename);

19voto

robertklep Points 29669

Il y a eu des propositions concernant l'exposition de ces variables par le biais de import.meta mais pour l'instant, vous avez besoin d'une solution de contournement que j'ai trouvée. ici :

// expose.js
module.exports = {__dirname};

// use.mjs
import expose from './expose.js';
const {__dirname} = expose;

5 votes

L'étape des crochets n'est pas nécessaire et cette méthode n'est d'ailleurs pas vraiment recommandée car si ./expose.js se trouve dans un autre répertoire, il donnera la valeur __dirname de ce répertoire, pas du script actuel... voir ma réponse

0 votes

C'est la seule façon que j'ai trouvée pour que la __dirname fonctionnent à la fois en mode CJS et ESM.

15voto

BananaAcid Points 279

J'ai utilisé :

import path from 'path';

const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname)));

decodeURI était important : j'utilisais des espaces et d'autres éléments dans le chemin sur mon système de test.

path.resolve() gère les urls relatives.

éditer :

pour prendre en charge Windows ( /C:/... => C:/... ) :

import path from 'path';

const __dirname = (() => {let x = path.dirname(decodeURI(new URL(import.meta.url).pathname)); return path.resolve( (process.platform == "win32") ? x.substr(1) : x ); })();

0 votes

J'ai toujours des problèmes avec BABEL, il n'accepte pas import.meta car import n'est pas accepté ici :)

0 votes

Vous pouvez utiliser Rollup (avec rollup-plugin-babel ) pour l'empaquetage ou esm pour l'exécution en direct comme les tests

5voto

user2962433 Points 31
import path from 'path';
const __dirname = path.join(path.dirname(decodeURI(new URL(import.meta.url).pathname))).replace(/^\\([A-Z]:\\)/, "$1");

Ce code fonctionne également sous Windows. (le remplacement est sûr sur les autres plateformes, puisque path.join renvoie les séparateurs back-slash uniquement sous Windows)

0 votes

Je l'ai essayé, et ça n'a pas marché pour moi sous Windows : Error: ENOENT: no such file or directory, open 'C:\C:\Projects\...such and such...\SomeFile.ts' . Le site code modifié par BananaAcid fonctionne, cependant.

2 votes

J'ai trouvé un petit correctif pour votre réponse, pour fonctionner sous Windows (fonctionnement confirmé) : [existing code].replace(/^\\([A-Z]:\\)/, "$1"); Ajouté comme suggestion d'édition.

0 votes

Bravo, ça a fait du bien !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X