← Node.js 速查手册 语义化版本 →

Node.js process.env怎么用?环境变量读取、设置与项目配置

著
原创 2026-10-14 Node.js 已有人查阅

一、process.env到底是什么

Node.js运行在操作系统之上,进程启动时,系统会把当前用户的环境变量注入到进程内部。process.env就是Node.js暴来的一个对象,用来访问这些环境变量。

它属于process模块,但不需要额外安装依赖,也不需要手动导入。绝大多数场景下直接写process.env就能拿到当前进程的环境变量。虽然可以写require('process'),但Node.js全局已经注入了process,实际项目里通常不这么写,多此一举还容易让新手误以为必须导入。

process.env返回的是一个对象,键和值都是字符串。即使系统里某个变量看起来是数字,读出来也是字符串。这一点后面会反复提到,因为它是很多配置读取错误的根源。

// 代码号学习编程:直接访问 process.env
console.log(process.env);

运行后你会看到一大堆键值对,包括系统路径、用户目录、临时目录、语言设置等。不同操作系统、不同终端、不同部署环境,内容差异很大。所以不要把process.env的输出当成固定结果,它反映的是当前进程的运行环境。

二、读取环境变量的正确姿势

1.直接点号读取

最常见的写法:

// 代码号学习编程:读取 PATH
const pathValue = process.env.PATH;
console.log(pathValue);

如果变量不存在,返回undefined,不会抛错。这一点和访问普通对象属性一致。

2.方括号读取

当变量名包含特殊字符,或者需要动态拼接时,用方括号:

// 代码号学习编程:动态读取
const key = 'ALLUSERSPROFILE';
const value = process.env[key];
console.log(value);

3.遍历所有环境变量

有时需要统计当前环境变量数量,或者做调试输出:

// 代码号学习编程:遍历环境变量
let count = 0;
for (const key in process.env) {
  console.log(`${key} = ${process.env[key]}`);
  count++;
}
console.log(`共 ${count} 个环境变量`);

这里有一个经验点:for...in会遍历可枚举属性,process.env本身是对象,通常没问题。但在现在Node.js中,更推荐用Object.keys(process.env)配合forEach或for...of,语义更清晰,也避免原型链干扰。

// 代码号学习编程:更现在的遍历方式
Object.keys(process.env).forEach((key) => {
  console.log(`${key} = ${process.env[key]}`);
});

三、动态增删环境变量

process.env不是只读的。你可以在运行时给它赋值,也可以删除某个键。

// 代码号学习编程:设置与删除
process.env.MY_APP_MODE = 'development';
console.log(process.env.MY_APP_MODE); // development

delete process.env.MY_APP_MODE;
console.log(process.env.MY_APP_MODE); // undefined

这个能力在测试和本地调试时有用。比如临时覆盖某个配置,跑完再删掉。但要注意:运行时修改只影响当前进程,不会写回操作系统,也不会影响其他进程。子进程如果继承环境变量,可能会拿到修改后的值,这一点在child_process场景下要特别留意。

实际项目中,不建议把process.env当普通对象随意增删。环境变量本质是进程启动时的外部配置,运行期频繁修改会让配置来源变得混乱,排查问题困难。更稳妥的做法是启动时读取一次,集中校验,后续使用内部配置对象。

四、PATH与PORT:两个高频点

1.PATH

process.env.PATH是操作系统查找可执行文件的路径列表。不同系统分隔符不同:Windows用分号,类Unix用冒号。

// 代码号学习编程:解析 PATH
const pathList = (process.env.PATH || '').split(process.platform === 'win32' ? ';' : ':');
console.log(pathList);

项目里如果需要调用外部命令,理解PATH有助于判断命令是否可被找到。但生产环境更推荐用绝对路径或明确依赖,而不是赌PATH里有某个目录。

2.PORT

很多Node.js服务通过process.env.PORT读取端口。注意它返回字符串,直接参与数值运算可能出问题。

// 代码号学习编程:端口解析
const port = parseInt(process.env.PORT, 10) || 3000;
console.log(port);

这里用parseInt并指定十进制,同时给默认值。不要写Number(process.env.PORT)就完事,因为空字符串会变成0,而0在某些场景下代表随机端口,容易引发误判。

个人经验:端口、超时、并发数这类配置,读出来后立刻做类型转换和范围校验,不要留在业务代码里到处parseInt。集中处理一次,后续使用更安全。

五、环境变量在项目中的典型用法

1.区分开发与生产

// 代码号学习编程:模式判断
const isProd = process.env.NODE_ENV === 'production';
if (isProd) {
  // 生产逻辑
} else {
  // 开发逻辑
}

NODE_ENV是约定俗成的变量,很多框架和库都会读取它。不要随意发明类似ENV、MODE的变量来替代,除非你有明确的统一规范。

2.读取敏感配置

数据库连接串、密钥等通常不写进代码,而是通过环境变量注入。

// 代码号学习编程:读取数据库地址
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
  throw new Error('缺少 DATABASE_URL 环境变量');
}

这里有一个重要原则:缺失的关键配置要尽早失败。不要等到连接数据库时才报错,启动阶段就检查,能减少很多排查成本。

3.提供默认值

// 代码号学习编程:默认值
const logLevel = process.env.LOG_LEVEL || 'info';

但默认值要谨慎。关键配置给默认值可能掩盖部署错误。比如数据库地址给了localhost,生产环境忘了配,结果连到本地,问题反而更隐蔽。

六、类型安全与错误处理

process.env的值是字符串或undefined。TypeScript项目里,直接读取可能得到string|undefined,需要处理。

// 代码号学习编程:TypeScript 中的安全读取
function getEnv(key: string): string {
  const value = process.env[key];
  if (value === undefined) {
    throw new Error(`环境变量 ${key} 未设置`);
  }
  return value;
}

const port = parseInt(getEnv('PORT'), 10);

如果不想每个变量都写一遍,可以集中定义一个配置模块:

// 代码号学习编程:集中配置
export const config = {
  port: parseInt(process.env.PORT || '3000', 10),
  dbUrl: process.env.DATABASE_URL || '',
  nodeEnv: process.env.NODE_ENV || 'development',
};

这样业务代码不直接碰process.env,配置来源清晰,测试时也容易替换。

现在框架中,Next.js、Vite、Nuxt等对环境变量有各自约定,比如前端暴露需要加前缀。使用前先看框架文档,不要直接把服务端环境变量透传到客户端,否则可能泄露敏感信息。

七、常见坑与注意事项

坑一:字符串
process.env.PORT是字符串,process.env.PORT+1会变成字符串拼接,不是数值加法。

坑二:跨平台差异
Windows和类Unix的环境变量名大小写敏感度不同。Windows通常不区分大小写,类Unix区分。写代码时尽量统一大写加下划线风格。

坑三:空字符串与undefined
变量存在但为空字符串,和变量不存在,是两种状态。判断时用===undefined还是!value,取决于业务语义。

坑四:运行时修改的副作用
前面提到过,修改process.env会影响子进程。如果用了child_process,要清楚传递了哪些变量。

坑五:不要在前端代码里直接读
浏览器里没有process.env。打包工具会在构建时替换,但替换规则因工具而异。写同构代码时要特别小心。

八、练习与思考

  1. 写一个函数,接收环境变量名数组,返回一个对象,缺失的变量抛出错误。

  2. 读取process.env.PATH,按当前系统分隔符拆分,打印每个路径。

  3. 模拟一个配置模块,支持从process.env读取端口、日志级别、数据库地址,并提供默认值。

  4. 思考:为什么关键配置缺失时,启动阶段报错比运行阶段报错更好?

← Node.js 速查手册 语义化版本 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号