环境变量是操作系统级别或应用运行环境中的动态命名值,用于在不修改代码的情况下改变应用的行为。在 Node.js 开发中,环境变量常用于存储敏感信息(如数据库密码、API 密钥)和环境特定的配置(如调试开关、服务端口)。本章将介绍如何有效地管理和使用环境变量。
Node.js 通过全局对象 process.env 提供对环境变量的访问。process.env 是一个包含所有用户环境变量的对象。例如,读取 PORT 变量:
const port = process.env.PORT || 3000;
console.log(`Server will run on port ${port}`);
直接设置环境变量的方式取决于操作系统(如 Linux 的 export,Windows 的 set),或者在运行 Node.js 命令时指定:
PORT=8080 node app.js
手动设置大量环境变量很繁琐,推荐使用 dotenv 库从 .env 文件中加载变量。它会将文件中的键值对读取并合并到 process.env 中。
安装:
npm install dotenv
在项目根目录创建 .env 文件:
# .env
PORT=3000
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=mysecret
API_KEY=abc123
在应用入口(如 app.js)尽早加载 dotenv:
require('dotenv').config();
console.log(process.env.PORT); // 3000
dotenv 会解析文件并设置环境变量,但不会覆盖已有的环境变量(除非设置 override 选项)。
如果 .env 文件不在根目录,可以指定路径:
require('dotenv').config({ path: '/custom/path/.env' });
通常,.env 文件用于开发环境,生产环境通过系统级环境变量或容器编排工具(如 Docker、Kubernetes)注入变量。可以通过条件加载避免在非开发环境意外使用 .env:
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config();
}
DB_HOST、API_KEY。1/0 或 true/false 字符串,并在代码中转换。在生产环境中,缺少关键环境变量可能导致应用启动失败或运行时错误。建议在启动时验证必要变量是否存在。可以使用 joi 或自定义函数。
const requiredEnv = ['DB_HOST', 'DB_USER', 'DB_PASSWORD'];
requiredEnv.forEach(key => {
if (!process.env[key]) {
console.error(`缺少必需的环境变量: ${key}`);
process.exit(1);
}
});
或者使用 envalid 库:
npm install envalid
const { cleanEnv, str, port } = require('envalid');
const env = cleanEnv(process.env, {
NODE_ENV: str({ choices: ['development', 'test', 'production'] }),
PORT: port({ default: 3000 }),
DB_HOST: str(),
DB_PASSWORD: str()
});
console.log(env.DB_HOST); // 经过验证和类型转换
环境变量在 Express 应用中非常常见,例如监听端口、数据库连接、JWT 密钥、API 端点等。
const express = require('express');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 3000;
const dbConfig = {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
};
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
有时你可能需要针对不同环境加载不同的配置。常见做法是使用多个 .env 文件,如 .env.development、.env.production,然后根据 NODE_ENV 加载对应的文件。
const envFile = `.env.${process.env.NODE_ENV || 'development'}`;
require('dotenv').config({ path: envFile });
但请注意,将敏感信息存储在文件中仍需谨慎,生产环境应优先使用系统环境变量。
.env 文件提交到版本控制系统(如 Git)。在 .gitignore 中添加 .env 和 .env.*,但可以提交一个示例文件 .env.example,包含必要键名和占位值。创建一个 config.js 模块,统一管理环境变量并提供默认值:
// config.js
require('dotenv').config();
const env = process.env;
const config = {
nodeEnv: env.NODE_ENV || 'development',
port: env.PORT || 3000,
database: {
host: env.DB_HOST || 'localhost',
port: env.DB_PORT || 5432,
name: env.DB_NAME || 'myapp',
user: env.DB_USER,
password: env.DB_PASSWORD
},
jwt: {
secret: env.JWT_SECRET,
expiresIn: env.JWT_EXPIRES_IN || '7d'
},
redis: {
url: env.REDIS_URL
}
};
// 验证必需变量
if (!config.database.user || !config.database.password) {
throw new Error('数据库用户名和密码必须配置');
}
if (!config.jwt.secret) {
throw new Error('JWT_SECRET 必须配置');
}
module.exports = config;
然后在应用中使用:
const config = require('./config');
console.log(config.database.host);
测试环境下可以动态设置环境变量,例如使用 cross-env 包确保跨平台兼容:
npm install --save-dev cross-env
然后在 package.json 的 scripts 中:
"scripts": {
"test": "cross-env NODE_ENV=test jest"
}
也可以在测试代码中使用 process.env 赋值,但注意会污染进程环境,建议使用后恢复。
.env 文件路径是否正确,确保 dotenv.config() 在访问变量前调用。PASSWORD="pass word"。const debug = process.env.DEBUG === 'true'。const port = parseInt(process.env.PORT, 10)。