最近剛好同事的 PR 遇到一個 bug, 和 Node.JS import(require) 有關, 大致上的狀況是這樣:
有一個 lib 名稱為 A.js
, 但是在使用的時候不小心變成小寫:
const a = require('lib/a');
神奇的是, 在開發階段, 這個錯誤並沒有被偵測到
換句話說, 在本機開發的情況下, 不論是在 VS code 或是 透過 command line 下指令, 程式都會正常運行
也就是, 檔案名稱的大小寫不會影響到 import
但是在線上的環境執行, 就直接噴錯誤了:
Error: Cannot find module 'lib/a'
...
看來在線上環境, 檔案的大小寫會有影響?
測試環境:
>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
// 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);
結果:
>node ./index.js
5 1
看起來在實驗的環境下, 大小寫的檔案名稱是有區別的
接下來將 A.js
改名為 B.js
結果是:
>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' ]
}
但是同樣的實驗場景, 換到本機後卻完全不同
測試環境:
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:.
同樣的專案架構, 但是明顯的檔案名稱不分大小寫:
> touch A.js
> touch a.js
> ls
A.js
先建立 A.js
之後, 再建立的 a.js
被系統認為是同樣的檔案
即便用 vim 來編輯, 系統也是將 A.js
與 a.js
當作一樣的檔案
接著在程式中實際測試:
const A = require('./lib/A.js');
const val1 = 3;
const val2 = 2;
const ans1 = A(val1, val2);
console.log(ans1);
結果:
>node index.js
5
如果將 import path 改為小寫:
const A = require('./lib/a.js');
...
結果:
>node index.js
5
看來在 MacOS 的環境, 檔案名稱是不分大小寫的
懷疑是和 OS 的 file system 有關, 這部份還需要再研究
先作個紀錄
看起來, 有大小寫區分反而比較少, 大都是 unix-like system
NodeJS
Computer Science
PoC-Study Message Queue in Node.js with BullMQ and Redis
Jan 17, 2025最近工作上會維護一個滿舊的專案,是用 Python2.7 開發的,用的是 web2py framework 基於習慣,不管是 new feature / refactoring,我都會寫 uniit test 不過我對於 python 比較陌生,而且還是 v2,一開始很擔心找不到輔助資料,幸好網路上還是有一些基於 v2 的就資料,搭配自己 try and error,算是順利解決 new feature 是一個很簡單的 http request,需要依照 response 的 status code 和 content result 作一些不同的 action 看起來是一個很尋常的 case,我也是這麼想,就到 google 上找 mock http request in Python2.7,第一個 stackoverflow 就有很不錯的討論
Jan 12, 2023利用 koa - A NodeJS framework 開發 RESTful API 的筆記 事前準備 因為過去的開發經驗, 一開始預想要使用的開發架構是: koa(2) + Typescript + openapi 在看了 npm trend 之後, 花了點時間研究了這個最熱門的 tsoa tsoa is a framework with integrated OpenAPI compiler to build Node.js serve-side applications using TypeScript. It can target express, hapi, koa and more frameworks at runtime. tsoa applications are type-safe by default and handle runtime validation seamlessly. 根據官網的說法, 他整合了 Typescript, OpenAPI, 並且支援各種 web framwork, 包含 express, hapi, 以及 koa
Dec 13, 2022Sequence Diagram title: Mutual Fund System User->Bank: 1. create user Bank->User Management: 1.1 create user User Management-->Bank: 1.2 return result Bank->Account Management: 1.4 create account Account Management-->Bank: 1.5 return result Bank-->User: 1.6 return result User->Bank: 2. sign agreement
Dec 12, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up