web-dev-qa-db-fra.com

Quelle est la différence entre __dirname et ./ dans node.js?

Lors de la programmation dans Node.js et du référencement de fichiers situés quelque part par rapport à votre répertoire actuel, existe-t-il une raison d'utiliser la variable __dirname au lieu d'un simple ./? J'ai utilisé ./ jusqu'à présent dans mon code et je viens de découvrir l'existence de __dirname, et je veux essentiellement savoir s'il serait judicieux de convertir mon ./ à cela, et si oui, pourquoi serait une bonne idée.

462
thisissami

L'essentiel

Dans Node.js, __dirname est toujours le répertoire dans lequel réside le script en cours d'exécution ( voir ceci ). Donc, si vous tapez __dirname dans /d1/d2/myscript.js, la valeur sera /d1/d2.

Par contre, . vous donne le répertoire à partir duquel vous avez exécuté la commande node dans la fenêtre de votre terminal (c’est-à-dire votre répertoire de travail) lorsque vous utilisez des bibliothèques telles que path et fs. Techniquement, cela commence comme votre répertoire de travail, mais vous pouvez le changer avec process.chdir().

L'exception est lorsque vous utilisez . avec require(). Le chemin à l'intérieur de require est toujours relatif au fichier contenant l'appel à require.

Par exemple...

Disons que votre structure de répertoire est

/dir1
  /dir2
    pathtest.js

et pathtest.js contient

var path = require("path");
console.log(". = %s", path.resolve("."));
console.log("__dirname = %s", path.resolve(__dirname));

et vous faites

cd /dir1/dir2
node pathtest.js

vous obtenez

. = /dir1/dir2
__dirname = /dir1/dir2

Votre répertoire de travail est /dir1/dir2 alors c'est ce que . résout. Puisque pathtest.js se trouve dans /dir1/dir2, c'est ce que __dirname résout également.

Cependant, si vous exécutez le script à partir de /dir1

cd /dir1
node dir2/pathtest.js

vous obtenez

. = /dir1
__dirname = /dir1/dir2

Dans ce cas, votre répertoire de travail était /dir1 alors c'est ce que . a résolu, mais __dirname est toujours résolu en /dir1/dir2.

Utiliser . dans require...

Si à l'intérieur de dir2/pathtest.js vous avez un appel require afin d'inclure un fichier à l'intérieur de dir1 vous devriez toujours faire

require('../thefile')

parce que le chemin à l'intérieur de require est toujours relatif au fichier dans lequel vous l'appelez. Cela n'a rien à voir avec votre répertoire de travail.

752
d512

./ fait référence au répertoire de travail en cours, sauf dans la fonction require(). Lorsque vous utilisez require(), il convertit ./ dans le répertoire du fichier en cours appelé. __dirname est toujours le répertoire du fichier actuel.

Par exemple, avec la structure de fichier suivante

/home/user/dir/files/config.json

{
  "hello": "world"
}

/home/user/dir/files/somefile.txt

text file

/home/user/dir/dir.js

var fs = require('fs');

console.log(require('./files/config.json'));
console.log(fs.readFileSync('./files/somefile.txt', 'utf8'));

Si je cd dans /home/user/dir et que je lance node dir.js je vais obtenir

{ hello: 'world' }
text file

Mais quand je lance le même script à partir de /home/user/ je reçois

{ hello: 'world' }

Error: ENOENT, no such file or directory './files/somefile.txt'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.<anonymous> (/home/user/dir/dir.js:4:16)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

Utiliser ./ a fonctionné avec require mais pas pour fs.readFileSync. En effet, pour fs.readFileSync, ./ est traduit en cwd (dans ce cas /home/user/). Et /home/user/files/somefile.txt n'existe pas.

151
fent