淺析 NodeJs 的幾種文件路徑

一、挖坑 & 掉坑:

緣起一段這樣的代碼:

fs.readFile('./docs/use.md', function (err, buffer) {
    if (err) {
      return console.log('error: ', err);
    }

    console.log('OK');
  });

本地運行時一切 OK,線上部署時卻死活找不到 ./docs/use.md 這個文件,後來才發現是因爲線上啓動應用時不是從當前目錄啓動了,不過爲什麼啓動腳本的位置也會影響這個路徑呢,且往下看。

二、填坑:

Node 中的文件路徑大概有 __dirname__filenameprocess.cwd()./ 或者 ../,前三個都是絕對路徑,爲了便於比較,./ 和 ../ 我們通過 path.resolve('./')來轉換爲絕對路徑。

先看一個簡單的栗子:

假如我們有這樣的文件結構:

app/
    -lib/
        -common.js
    -model
        -task.js
        -test.js

在 task.js 裏編寫如下的代碼:

var path = require('path');

console.log(__dirname);
console.log(__filename);
console.log(process.cwd());
console.log(path.resolve('./'));

在 model 目錄下運行 node task.js 得到的輸出是:

/Users/guo/Sites/learn/app/model
/Users/guo/Sites/learn/app/model/task.js
/Users/guo/Sites/learn/app/model
/Users/guo/Sites/learn/app/model

然後在 app 目錄下運行 node model/task.js,得到的輸出是:

/Users/guo/Sites/learn/app/model
/Users/guo/Sites/learn/app/model/task.js
/Users/guo/Sites/learn/app
/Users/guo/Sites/learn/app

那麼,不好意思不是問題來了~T_T,我們可以得出一些膚淺的結論了:

  • __dirname: 總是返回被執行的 js 所在文件夾的絕對路徑
  • __filename: 總是返回被執行的 js 的絕對路徑
  • process.cwd(): 總是返回運行 node 命令時所在的文件夾的絕對路徑
  • ./: 跟 process.cwd() 一樣、一樣、一樣的嗎?

我明明記得在 require('../lib/common') 裏一直都是各種相對路徑寫,也沒見報什麼錯啊,我們還在再來個栗子吧,還是上面的結構,'model/task.js' 裏的代碼改成:

var fs = require('fs');
var common = require('../lib/common');

fs.readFile('../lib/common.js', function (err, data) {
    if (err) return console.log(err);
    console.log(data);
});

在 model 目錄下運行 node task.js,一切 Ok,沒有報錯。然後在 app 目錄下運行 node model/task.js,然後很果斷滴報錯了:

那麼這下問題真的都是來了,按照上面的理論,在 app 下運行時,../lib/common.js 會被轉成 /Users/guo/Sites/learn/lib/common.js,這個路徑顯然是不存在的,但是從運行結果可以看出 require('../lib/common') 是 OK 的,只是 readFile 時報錯了。

那麼關於 ./ 正確的結論是:

在 require() 中使用是跟 __dirname 的效果相同,不會因爲啓動腳本的目錄不一樣而改變,在其他情況下跟 process.cwd() 效果相同,是相對於啓動腳本所在目錄的路徑。

三、總結:

只有在 require() 時才使用相對路徑(./, ../) 的寫法,其他地方一律使用絕對路徑,如下:

// 當前目錄下
path.dirname(__filename) + '/test.js';
// 相鄰目錄下
path.resolve(__dirname, '../lib/common.js');

四、參考鏈接:

以上😄。

see:https://github.com/imsobear/blog/issues/48

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章