dotenv 是一个零依赖的 Node.js 模块,用于将环境变量从 .env 文件加载到 process.env 中。
简单来说,它让你可以把配置信息(如数据库密码、API密钥等)从代码中分离出来 ,放到一个单独的 .env 文件中管理。
一、为什么需要 dotenv?
问题场景
javascript
// ❌ 不好的做法:硬编码配置
const dbPassword = 'mySecretPassword123';
const apiKey = 'sk-abc123xyz';
硬编码的问题:
- 敏感信息泄露风险(提交到 Git)
- 不同环境(开发/测试/生产)需要不同配置时很麻烦
- 配置散落在代码各处,难以管理
dotenv 的解决方案
javascript
// ✅ 好的做法:从环境变量读取
const dbPassword = process.env.DB_PASSWORD;
const apiKey = process.env.API_KEY;
这些环境变量从 .env 文件加载,而 .env 文件不提交到 Git。
二、基本用法
1. 安装
bash
npm install dotenv
2. 创建 .env 文件
bash
# .env
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=s3cr3t
API_KEY=sk-abc123xyz
PORT=3000
NODE_ENV=development
3. 在代码中使用
javascript
// 方式1:尽早引入(推荐)
import 'dotenv/config';
console.log(process.env.DB_HOST); // localhost
console.log(process.env.API_KEY); // sk-abc123xyz
console.log(process.env.PORT); // 3000
javascript
// 方式2:手动配置
import dotenv from 'dotenv';
dotenv.config();
console.log(process.env.DB_PASSWORD); // s3cr3t
4. 运行
bash
node index.js
# 自动加载 .env 文件中的变量
三、高级用法
1. 指定 .env 文件路径
javascript
dotenv.config({ path: '/custom/path/.env' });
2. 多环境配置
bash
.env.development # 开发环境
.env.production # 生产环境
.env.test # 测试环境
javascript
// 根据 NODE_ENV 加载不同文件
import dotenv from 'dotenv';
import path from 'path';
const envFile = `.env.${process.env.NODE_ENV || 'development'}`;
dotenv.config({ path: path.resolve(process.cwd(), envFile) });
3. 覆盖已存在的环境变量
javascript
// 默认不会覆盖已存在的环境变量
dotenv.config();
// 强制覆盖
dotenv.config({ override: true });
4. 解析已有字符串
javascript
import dotenv from 'dotenv';
const envConfig = dotenv.parse('DB_HOST=localhost\nDB_USER=root');
console.log(envConfig.DB_HOST); // localhost
四、配合 Git 的最佳实践
文件管理策略
bash
# 提交到 Git(包含示例,不含真实值)
.env.example
# 不提交到 Git(真实配置)
.env
.env.local
.env.development.local
.gitignore 配置
gitignore
# .gitignore
.env
.env.local
.env.*.local
.env.example 示例
bash
# .env.example(提交到 Git)
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password_here
API_KEY=your_api_key_here
PORT=3000
团队成员克隆项目后,复制 .env.example 为 .env 并填入真实值:
bash
cp .env.example .env
# 编辑 .env 填入真实配置
五、常见使用场景
场景1:Web 应用配置
javascript
import express from 'express';
import 'dotenv/config';
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({ env: process.env.NODE_ENV });
});
app.listen(port);
场景2:数据库连接
javascript
import mongoose from 'mongoose';
import 'dotenv/config';
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/myapp';
mongoose.connect(MONGODB_URI)
.then(() => console.log('Connected to MongoDB'));
场景3:第三方 API 密钥
javascript
import OpenAI from 'openai';
import 'dotenv/config';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
场景4:配置不同环境
javascript
// config/index.js
import 'dotenv/config';
export const config = {
port: process.env.PORT || 3000,
database: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
name: process.env.DB_NAME,
},
redis: {
url: process.env.REDIS_URL,
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN,
},
};
六、安全性注意事项
| 注意事项 | 说明 |
|---|---|
| 永远不要提交 .env 到 Git | 包含敏感信息 |
| 使用 .env.example | 提供配置模板 |
| 限制 .env 文件权限 | chmod 600 .env(仅所有者可读写) |
| 生产环境慎重使用 | 生产环境建议直接用系统环境变量 |
| 不要在客户端代码中使用 | .env 只在服务端,前端构建时需用其他方案 |
七、生产环境 vs 开发环境
| 环境 | 推荐做法 |
|---|---|
| 开发环境 | 使用 dotenv + .env 文件 |
| 生产环境 | 使用系统环境变量(如 Docker、K8s、PM2) |
| CI/CD | 在 CI 平台配置环境变量 |
生产环境示例:
bash
# 不安装 dotenv,直接设置系统变量
export DB_PASSWORD=s3cr3t
export API_KEY=sk-abc123
# 或使用 Docker
docker run -e DB_PASSWORD=s3cr3t -e API_KEY=sk-abc myapp
# 或使用 PM2
pm2 start app.js --env production
javascript
// 代码中不需要 dotenv,直接读取系统变量
const dbPassword = process.env.DB_PASSWORD;
八、替代方案
| 方案 | 说明 | 适用场景 |
|---|---|---|
| dotenv | 最简单,零依赖 | 大多数 Node.js 项目 |
| dotenv-flow | 支持多环境继承 | 复杂多环境配置 |
| env-cmd | 命令行工具 | npm scripts 中使用 |
| cross-env | 跨平台设置环境变量 | npm scripts 兼容 Windows |
| 系统环境变量 | 无依赖 | 生产环境、Docker |
九、常见问题
Q: dotenv 必须在文件最顶部引入吗?
A : 是的,需要在其他代码读取 process.env 之前加载。
javascript
// ✅ 正确
import 'dotenv/config';
import express from 'express'; // 之后才读取
// ❌ 错误
import express from 'express';
import 'dotenv/config'; // 太晚了,express 可能已经读取了环境变量
Q: 为什么 process.env 的值是 undefined?
A: 可能原因:
- 没有引入 dotenv
- .env 文件不存在或路径错误
- 变量名大小写写错
Q: 可以同时使用多个 .env 文件吗?
A: 可以,但需要自己组合:
javascript
dotenv.config({ path: '.env.common' });
dotenv.config({ path: '.env.local', override: true });
十、总结
| 特性 | 说明 |
|---|---|
| 作用 | 将配置从代码中分离到 .env 文件 |
| 核心价值 | 安全性(避免泄露)、环境适配、配置集中管理 |
| 使用方式 | import 'dotenv/config' 后读取 process.env.xxx |
| 最佳实践 | .env 不提交 Git,提供 .env.example 模板 |
| 生产环境 | 建议用系统环境变量替代 .env 文件 |
一句话总结:dotenv 让配置管理变得简单、安全、环境友好,是现代 Node.js 项目的标配工具之一。