- Published on
Node.js 環境變數載入順序解析:cross-env 與 dotenv 的交互作用
- Authors
- Name
剛好再設定環境變數時,遇到一個有點有趣的問題:
- 在 script 中設定
"dev": "cross-env APP_ENV=local node server.js"
- 在 env.local 中設定 APP_ENV="local-app-env"
那最終會顯示 local
還是 local-app-env
?
案例背景
有以下的專案設定:
package.json
{
"scripts": {
"dev": "cross-env APP_ENV=local node server.js"
}
}
.env.local
APP_ENV="local-app-env"
環境變數載入邏輯
// next.config.js
const path = require('path');
const APP_ENV = process.env.APP_ENV || 'development';
// 動態載入對應的 .env 檔案
const envPath = path.resolve(__dirname, `.env.${APP_ENV}`);
dotenv.config({ path: envPath });
module.exports = {
env: {
APP_ENV: process.env.APP_ENV,
},
};
最終結果
dotenv 載入但不覆寫,因為 process.env.APP_ENV 已經被 cross-env 設定為 "local",dotenv 會保持現有值不變。
關鍵觀念
1. dotenv 預設不會覆寫現有的環境變數
在這個案例中,看到一個重要的概念:dotenv 預設不會覆寫現有的環境變數。
// 預設行為:不覆寫現有環境變數
dotenv.config({ path: envPath });
// 如果想要覆寫現有環境變數
dotenv.config({ path: envPath, override: true });
2. 載入順序的重要性
環境變數的載入順序會直接影響最終的結果,但要注意 dotenv 的保護機制:
- 系統環境變數
- cross-env 設定的變數
- dotenv 載入的檔案內容(只設定尚未存在的變數)
3. 避免循環依賴
不要在 .env
檔案中重新定義用於選擇該檔案的環境變數:
# ❌ 不建議:在 .env.local 中重新定義 APP_ENV
APP_ENV="something-else"
# ✅ 建議:移除或保持一致
# APP_ENV="local"
結論
實際 log 出來後才知道以上的小知識,還算蠻有趣的。
1. 核心要點
- dotenv 的保護機制:預設情況下,dotenv 不會覆寫已經存在的環境變數,這是一個重要的安全特性
- 載入順序的重要性:cross-env 設定的變數會優先於 dotenv 載入的變數
- 避免循環依賴:不要在環境檔案中重新定義用於選擇該檔案的環境變數
2. 實際應用
這在微服務架構、多環境部署、CI/CD 流程中特別重要,理解後能避免環境變數衝突,確保應用程式在不同環境中都能正確運行。