dotenv详解

14 阅读4分钟

dotenv 是一个零依赖的 Node.js 模块,用于将环境变量从 .env 文件加载到 process.env 中。

简单来说,它让你可以把配置信息(如数据库密码、API密钥等)从代码中分离出来,放到一个单独的 .env 文件中管理。


一、为什么需要 dotenv?

问题场景

// ❌ 不好的做法:硬编码配置
const dbPassword = 'mySecretPassword123';
const apiKey = 'sk-abc123xyz';

硬编码的问题

  • 敏感信息泄露风险(提交到 Git)
  • 不同环境(开发/测试/生产)需要不同配置时很麻烦
  • 配置散落在代码各处,难以管理

dotenv 的解决方案

// ✅ 好的做法:从环境变量读取
const dbPassword = process.env.DB_PASSWORD;
const apiKey = process.env.API_KEY;

这些环境变量从 .env 文件加载,而 .env 文件不提交到 Git


二、基本用法

1. 安装

npm install dotenv

2. 创建 .env 文件

# .env
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=s3cr3t
API_KEY=sk-abc123xyz
PORT=3000
NODE_ENV=development

3. 在代码中使用

// 方式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
// 方式2:手动配置
import dotenv from 'dotenv';
dotenv.config();

console.log(process.env.DB_PASSWORD); // s3cr3t

4. 运行

node index.js
# 自动加载 .env 文件中的变量

三、高级用法

1. 指定 .env 文件路径

dotenv.config({ path: '/custom/path/.env' });

2. 多环境配置

.env.development    # 开发环境
.env.production     # 生产环境
.env.test           # 测试环境
// 根据 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. 覆盖已存在的环境变量

// 默认不会覆盖已存在的环境变量
dotenv.config(); 

// 强制覆盖
dotenv.config({ override: true });

4. 解析已有字符串

import dotenv from 'dotenv';

const envConfig = dotenv.parse('DB_HOST=localhost\nDB_USER=root');
console.log(envConfig.DB_HOST); // localhost

四、配合 Git 的最佳实践

文件管理策略

# 提交到 Git(包含示例,不含真实值)
.env.example

# 不提交到 Git(真实配置)
.env
.env.local
.env.development.local

.gitignore 配置

# .gitignore
.env
.env.local
.env.*.local

.env.example 示例

# .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 并填入真实值:

cp .env.example .env
# 编辑 .env 填入真实配置

五、常见使用场景

场景1:Web 应用配置

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:数据库连接

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 密钥

import OpenAI from 'openai';
import 'dotenv/config';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

场景4:配置不同环境

// 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 平台配置环境变量

生产环境示例

# 不安装 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
// 代码中不需要 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 之前加载。

// ✅ 正确
import 'dotenv/config';
import express from 'express';  // 之后才读取

// ❌ 错误
import express from 'express';
import 'dotenv/config';  // 太晚了,express 可能已经读取了环境变量

Q: 为什么 process.env 的值是 undefined?

A: 可能原因:

  1. 没有引入 dotenv
  2. .env 文件不存在或路径错误
  3. 变量名大小写写错

Q: 可以同时使用多个 .env 文件吗?

A: 可以,但需要自己组合:

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 项目的标配工具之一。