# Node.JS import(require) path 最近剛好同事的 PR 遇到一個 bug, 和 Node.JS import(require) 有關, 大致上的狀況是這樣: 有一個 lib 名稱為 ```A.js```, 但是在使用的時候不小心變成小寫: ```javascript const a = require('lib/a'); ``` 神奇的是, 在開發階段, 這個錯誤並沒有被偵測到 換句話說, 在本機開發的情況下, 不論是在 VS code 或是 透過 command line 下指令, 程式都會正常運行 也就是, 檔案名稱的大小寫不會影響到 import 但是在線上的環境執行, 就直接噴錯誤了: ```shell Error: Cannot find module 'lib/a' ... ``` 看來在線上環境, 檔案的大小寫會有影響? --- ## 實驗 測試環境: ```shell >cat /etc/os-release PRETTY_NAME="Ubuntu 22.10" NAME="Ubuntu" VERSION_ID="22.10" VERSION="22.10 (Kinetic Kudu)" VERSION_CODENAME=kinetic ID=ubuntu ID_LIKE=debian HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" UBUNTU_CODENAME=kinetic LOGO=ubuntu-logo >tree . |-- index.js |-- lib | |-- A.js | `-- a.js `-- package.json ``` ```javascript // A.js module.exports = (a, b) => { return a + b; } // a.js module.exports = (a, b) => { return a - b; } // index.js const A = require('./lib/A'); const a = require('./lib/a'); const v1 = 3; const v2 = 2; const ans1 = A(v1, v2); const ans2 = a(v1, v2); console.log(ans1, ans2); ``` 結果: ```shell >node ./index.js 5 1 ``` 看起來在實驗的環境下, 大小寫的檔案名稱是有區別的 接下來將 ```A.js``` 改名為 ```B.js``` 結果是: ```shell >node ./index.js node:internal/modules/cjs/loader:1029 throw err; ^ Error: Cannot find module './lib/A' Require stack: - /home/edlo/projects/node/demo-package/index.js at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1026:15) at Function.Module._load (node:internal/modules/cjs/loader:871:27) at Module.require (node:internal/modules/cjs/loader:1098:19) at require (node:internal/modules/cjs/helpers:108:18) at Object.<anonymous> (/home/edlo/projects/node/demo-package/index.js:1:11) at Module._compile (node:internal/modules/cjs/loader:1196:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1250:10) at Module.load (node:internal/modules/cjs/loader:1074:32) at Function.Module._load (node:internal/modules/cjs/loader:909:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/edlo/projects/node/demo-package/index.js' ] } ``` 但是同樣的實驗場景, 換到本機後卻完全不同 測試環境: ```shell neofetch 'c. edlo@MacBook-Pro.local ,xNMM. ---------------------- .OMMMMo OS: macOS 13.2.1 22D68 arm64 OMMM0, Host: MacBookPro18,1 .;loddo:' loolloddol;. Kernel: 22.3.0 cKMMMMMMMMMMNWMMMMMMMMMM0: Uptime: 1 day, 7 hours, 19 mins .KMMMMMMMMMMMMMMMMMMMMMMMWd. Packages: 131 (brew) XMMMMMMMMMMMMMMMMMMMMMMMX. Shell: zsh 5.8.1 ;MMMMMMMMMMMMMMMMMMMMMMMM: Resolution: 2560x1440, 1496x967, 1920x1080 :MMMMMMMMMMMMMMMMMMMMMMMM: DE: Aqua .MMMMMMMMMMMMMMMMMMMMMMMMX. WM: Quartz Compositor kMMMMMMMMMMMMMMMMMMMMMMMMWd. WM Theme: Blue (Dark) .XMMMMMMMMMMMMMMMMMMMMMMMMMMk Terminal: WarpTerminal .XMMMMMMMMMMMMMMMMMMMMMMMMK. CPU: Apple M1 Pro kMMMMMMMMMMMMMMMMMMMMMMd GPU: Apple M1 Pro ;KMMMMMMMWXXWMMMMMMMk. Memory: 6422MiB / 32768MiB .cooc,. .,coo:. ``` 同樣的專案架構, 但是明顯的檔案名稱不分大小寫: ```shell > touch A.js > touch a.js > ls A.js ``` 先建立 ```A.js``` 之後, 再建立的 ```a.js``` 被系統認為是同樣的檔案 即便用 vim 來編輯, 系統也是將 ```A.js``` 與 ```a.js``` 當作一樣的檔案 接著在程式中實際測試: ```javascript const A = require('./lib/A.js'); const val1 = 3; const val2 = 2; const ans1 = A(val1, val2); console.log(ans1); ``` 結果: ```shell >node index.js 5 ``` 如果將 import path 改為小寫: ```javascript const A = require('./lib/a.js'); ... ``` 結果: ```shell >node index.js 5 ``` 看來在 MacOS 的環境, 檔案名稱是不分大小寫的 懷疑是和 OS 的 file system 有關, 這部份還需要再研究 先作個紀錄 --- ## 補充 [檔名在不同OS中的比較](https://zh.wikipedia.org/zh-tw/%E6%AA%94%E6%A1%88%E5%90%8D%E7%A8%B1#%E6%96%87%E4%BB%B6%E5%90%8D%E5%9C%A8%E4%B8%8D%E5%90%8COS%E4%B8%AD%E7%9A%84%E6%AF%94%E8%BE%83) [在 macOS 中完美配置文件名大小写敏感](https://zhuanlan.zhihu.com/p/35908178) 看起來, 有大小寫區分反而比較少, 大都是 unix-like system ###### tags: `NodeJS` `Computer Science`