# 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`