Qual é a diferença entre __dirname e ./ in node.js?

Ao programar em Node.js e referenciar arquivos que estão localizados em algum lugar em relação ao seu diretório atual, existe algum motivo para usar a variável __dirname vez de apenas um ./ ? Regular? Eu tenho usado o ./ até agora no meu código e acabei de descobrir a existência do __dirname , e essencialmente quero saber se seria inteligente converter o meu ./s para isso, e em caso afirmativo, por que isso seria inteligente? idéia.

A essência

Em Node.js, __dirname é sempre o diretório no qual o script atualmente em execução reside ( veja este ). Então, se você digitar __dirname em /d1/d2/myscript.js , o valor será /d1/d2 .

Por outro lado . fornece o diretório a partir do qual você executou o comando node em sua janela de terminal (ou seja, seu diretório de trabalho).

A exceção é quando você usa . com require() . O caminho que o interior require é sempre relativo ao arquivo que contém a chamada a ser require .

Por exemplo…

Digamos que sua estrutura de diretórios seja

 /dir1 /dir2 pathtest.js 

e pathtest.js contém

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

e você faz

 cd /dir1/dir2 node pathtest.js 

você consegue

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

Seu diretório de trabalho é /dir1/dir2 e é isso . resolve para. Desde pathtest.js está localizado em /dir1/dir2 é o que __dirname resolve também.

No entanto, se você executar o script de /dir1

 cd /dir1 node dir2/pathtest.js 

você consegue

 . = /dir1 __dirname = /dir1/dir2 

Nesse caso, seu diretório de trabalho era /dir1 e é isso . resolvido para, mas __dirname ainda resolve para /dir1/dir2 .

Usando . dentro de require

Se dentro de dir2/pathtest.js você tiver uma chamada de dir2/pathtest.js para include um arquivo dentro de dir1 você sempre faria

 require('../thefile') 

porque o caminho dentro require sempre é relativo ao arquivo no qual você está chamando. Não tem nada a ver com o seu diretório de trabalho.

./ refere-se ao diretório de trabalho atual, exceto na function require() . Ao usar require() , ele traduz ./ para o diretório do arquivo atual chamado. __dirname é sempre o diretório do arquivo atual.

Por exemplo, com a seguinte estrutura de arquivos

/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')); 

Se eu cd em /home/user/dir e execute o node dir.js eu vou conseguir

 { hello: 'world' } text file 

Mas quando eu corro o mesmo script de /home/user/ recebo

 { 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. (/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) 

Usando ./ trabalhou com require mas não para fs.readFileSync . Isso porque para fs.readFileSync , ./ traduz no cwd (neste caso /home/user/ ). E /home/user/files/somefile.txt não existe.