90 秒總覽
啟動流程是整個系統的入口邏輯,它負責決定「這次執行走快速路徑還是完整初始化」。快速路徑用於 --version、--help 等即時回覆;完整路徑會依序載入 profiler、主模組、設定檔、上下文工廠,最後進入互動迴圈。理解啟動流程的效能分層策略,是掌握整個系統的第一步。
執行路徑(主骨架)
if (args[0] === '--version') {
console.log(VERSION)
return
}
const { profileCheckpoint } = await import('../utils/startupProfiler.js')
profileCheckpoint('cli_entry')
await import('../main.js')
先用快速路徑攔截最輕量的請求,避免整個系統都載入;完整路徑才啟動 profiler 並進入主模組。
讀取 CLI 參數
如果是快速路徑(--version / --help):
直接回應並結束
否則:
載入 profiler,記錄 cli_entry 時間點
載入主模組 main.js
載入設定檔與全域組態
建立上下文工廠(context factory)
進入互動迴圈(REPL)
flowchart TD
A[CLI 參數輸入] --> B{快速路徑檢查}
B -->|是: --version / --help| C[立即回應並結束]
B -->|否| D[載入 profiler]
D --> E[記錄 cli_entry checkpoint]
E --> F[載入主模組 main.js]
F --> G[載入設定檔]
G --> H[建立上下文工廠]
H --> I[進入互動迴圈 REPL]
路徑判讀重點
- 入口只做參數解析與分流,不載入任何功能模組。
- profiler 在入口層就啟動,確保完整記錄啟動過程。
- 主模組透過 dynamic import 延遲載入,縮短快速路徑回應時間。
- 設定檔與上下文工廠在主模組內依序初始化,順序不可調換。
關鍵決策(為什麼這樣設計)
決策 1:CLI 入口只做分流,不做初始化
原因:入口檔案的唯一職責是判斷走快速路徑還是完整路徑。把初始化邏輯留給主模組,保持入口輕量且啟動速度最快。
代價:新增快速路徑指令時必須同步更新入口的分流邏輯,維護者需注意入口與主模組的職責邊界。
決策 2:使用 dynamic import 延遲載入重模組
原因:用 await import() 確保只有真正需要完整功能時才載入主模組。--version 等快速路徑完全不觸發重模組載入,回應時間可控制在毫秒等級。
代價:動態載入讓靜態分析工具難以追蹤完整依賴樹,IDE 的跳轉與自動補全可能失效。
決策 3:profiler 在入口層就開始記錄啟動效能
原因:啟動效能的瓶頸往往在入口到主模組載入完成之間。在入口層就啟動 profiler 並記錄 cli_entry checkpoint,才能完整測量這段關鍵路徑。
代價:profiler 本身也是一次 dynamic import,會為快速路徑增加微小延遲(但只影響完整路徑)。
替代方案與取捨
| 方案 | 優點 | 缺點 | 為何未採用/何時可採用 |
|---|---|---|---|
| 全量同步載入(啟動時載入所有模組) | 程式碼路徑單純,無動態載入複雜度 | 冷啟動慢,--version 也要等完整初始化 |
模組體積小時可行;目前系統規模過大,快速路徑延遲無法接受 |
| 入口直接初始化(不做分層) | 邏輯集中,不需跨檔案追蹤 | 入口檔案膨脹,所有請求都承受完整初始化成本 | 極小型工具可行;目前入口職責應保持輕量分流 |
| profiler 全程啟用(含快速路徑) | 所有路徑皆有效能數據,診斷更完整 | 快速路徑多一次 dynamic import,增加不必要延遲 | 偵錯模式下可啟用;正式環境只在完整路徑啟用即可 |
失敗路徑與防護
Failure 1:參數解析錯誤導致路由失敗
症狀:使用者輸入未預期的參數格式(如 --versoin 拼寫錯誤),導致既未走快速路徑也未正確進入完整初始化。
防護:在入口層加入預設的 fallback 邏輯:不符合快速路徑條件的參數一律走完整路徑,由主模組統一處理無效參數並輸出提示。
Failure 2:dynamic import 模組解析失敗
症狀:await import('../main.js') 拋出 ERR_MODULE_NOT_FOUND 或語法錯誤,使用者看到未處理的例外堆疊。
防護:在入口層以 try/catch 包裹 dynamic import,捕獲載入失敗後輸出可讀的錯誤訊息與排查建議(如檢查安裝是否完整)。
Failure 3:設定檔載入超時或格式錯誤
症狀:設定檔路徑不存在、JSON 格式錯誤或檔案系統回應過慢,導致初始化卡住或拋出解析例外。
防護:設定檔載入加入超時機制與格式驗證;當設定檔無法載入時,使用合理的預設值繼續啟動,並向使用者發出警告。
實作驗證(你改完要怎麼確認)
- 確認
--version回應時間 < 100ms,不觸發完整初始化路徑。 - 確認 profiler 的
cli_entrycheckpoint 有正確記錄,可在日誌中查閱。 - 確認互動模式正確進入:完整路徑走完後,使用者能看到互動提示符並正常輸入。
- 模擬主模組載入失敗:確認 try/catch 有攔截錯誤,輸出可讀的錯誤訊息。
- 模擬設定檔格式錯誤:確認系統以預設值繼續啟動,並顯示警告。
前三項是最低可接受驗證集,後兩項針對失敗路徑做回歸測試。