Node.js 入口點判斷(require.main === module)
這是 Node.js 常見的入口點判斷寫法,用來區分「直接執行這個檔案」和「被其他檔案 import 引用」兩種情況。
這段程式碼在做什麼?
if (require.main === module) {
main();
}
module:目前這個檔案本身(例如migrate.ts編譯後的模組)require.main:Node 程序啟動時載入的第一個模組,也就是你實際執行的入口檔
當 require.main === module 為 true 時,代表這個檔案是直接被執行的,例如:
npm run migrate:up
# 或
node dist/scripts/migrate.js up
這時才會呼叫 main(),開始跑 CLI 邏輯。
為什麼要這樣寫?
如果其他檔案 import 了同一支 script(或編譯後的 .js),例如:
import './migrate'; // 或 import { something } from './migrate'
此時 require.main !== module,不會自動執行 main(),避免 import 時意外觸發 migration 或其他副作用。
實務範例
以 migration script 為例,main() 通常會:
- 讀取
process.argv解析子指令 - 建立
MigrationRunner - 執行
up/down/status/create等操作
這段判斷確保只有在你刻意執行這個 script 時才會跑上述邏輯;被其他模組引用時,只會載入可匯出的函式或設定,不會啟動 CLI。
CommonJS 與 ES Module 對照
上述寫法屬於 CommonJS。若專案使用純 ES Module,常見的等價寫法如下:
import { pathToFileURL } from 'node:url';
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
main();
}
| 模組系統 | 判斷方式 | 備註 |
|---|---|---|
| CommonJS | require.main === module | TypeScript 編譯成 CJS 時的標準做法 |
| ES Module | import.meta.url 與入口檔比對 | 建議用 pathToFileURL,避免路徑格式差異 |
若專案編譯成 CommonJS,require.main === module 仍是標準且常見的做法。