使用相對路徑產生的問題
資料夾結構
1 | test/ |
path.js 中的程式碼
1 | fs.readFile('../lib/common.js','utf8' , function (err, data) { |
在 nodejs 資料夾下執行 node path.js
, 可以順利讀取檔案
退回一個資料夾, 在 test 資料夾下執行 node nodejs/path.js
, 則是報錯了。
這是 Node 的機制所導致的, 在 Node 中, 文件裡的相對路徑代表的是執行 node 時所在的資料夾的相對路徑, 並不是你所執行的 JS 檔本身的相對路徑。
在這個例子中, 如果在 ~/DeskTop/test
這個資料夾執行 node nodejs/path.js
指令, 程式碼中 readFile 內參數路徑 ../lib/common.js 會被解釋成 ~/DeskTop/lib/common.js
, 而顯然這個資料路徑是不存在的。
使用絕對路徑
在 Node.js 中, 大概有 __dirname
、__filename
、process.cwd()
或者 ./
和 ../
, 前三者都是絕對路徑, 為了便於比較 ./
和 ../
我們使用 path.resolve('./')
來轉換為絕對路徑
和上例一樣的資料結構, 將 path.js 改成:
1 | const path = require('path') |
在當下資料夾, 也就是 nodejs
資料夾執行命令 node path.js
, 看看輸出結果:
1 | __dirname: C:\Users\Dylanliu\Desktop\test\nodejs |
接著退回一個層級資料夾, 到了 test
資料夾執行命令 node nodejs/path.js
, 看看輸出結果:
1 | __dirname: C:\Users\Dylanliu\Desktop\test\nodejs |
再退一個層級資料夾, 到 Desktop
中執行命令 node test/nodejs/path.js
, 看看輸出結果:
1 | __dirname: C:\Users\Dylanliu\Desktop\test\nodejs |
由上面的實驗結果可以歸納以下結論:
1 | - __dirname: 總是回傳被執行 js 檔所在資料夾的絕對路徑 |
正確路徑使用習慣
由上面的實驗可以知道, 在 Node 中使用相對路徑進行檔案讀取是很危險的, 建議一律都透過絕對路徑的方式來處理
將 path.js 改成這樣:
1 | const fs = require('fs') |
在 nodejs 資料夾下執行 node path.js
, 順利讀取檔案
退回一個資料夾, 在 test 資料夾下執行 node nodejs/path.js
, 一樣順利讀取檔案
path.join() 方法
path.join() 是 path 核心模組提供的一個方法, 可以幫助開法者在拼接路徑字串時, 減少出錯機率
來做個實驗, 首先在終端機執行 node
, 進入 REPL 模式, 輸入程式碼做測試
1 | path.join('C:/file', 'fileB') |
輸出:
1 | 'C:\\file\\fileB' |
若在手動拚字串的過程中少了或多了一個 /
符號, 很容易導致路徑問題, 產生一些低級錯誤。如果使用 path.join()
這個方法就能有效避免失誤機率發生
1 | path.join('C:/file', 'fileB', '//fileC', 'fileD') |
輸出:
1 | 'C:\\file\\fileB\\fileC\\fileD' |
require 的相對路徑
還記得我們在 Node 中使用 require 時好像也常常使用相對路徑來引入自己寫的 JS 檔, 對吧?這樣也會有一樣的問題嗎?來試試看吧
延續一樣的資料夾結構
1 | test/ |
common.js 內容
1 | exports.A = 'A' |
在 path.js 撰寫程式碼, 透過 require 和 readFile 來測試, 讀取的檔案同樣是 common.js
, 接著測試在不同資料夾執行腳本時, 兩者會不會有差異
1 | var fs = require('fs') |
在 nodejs 資料夾下執行指令 node path.js
, 想當然是不會報錯的。
退回一個資料夾, 在 test 資料夾下執行指令 node nodejs/path.js
這下問題來了, test 資料夾下執行指令時, 為什麼 require 是 OK 的, 只有 readFile 會報錯呢?
關於相對路徑的結論是
只有在 require()
中使用時, 效果相同於 __dirname
, 不會因為啟動腳本的資料夾不同而改變, 在其他情況下則跟 process.cwd()
效果相同, 是相對於啟動腳本所在資料夾的路徑。因此, 只有在 require()
時才能使用相對路徑, 其他情況一律使用絕對路徑是最安全的方式。