Node.js中如何将.env内容读取到自定义变量而非直接写入process.env
实现方案
不需要额外替换dotenv库,用其内置能力就能实现完全不污染原有process.env的配置读取,核心是不要用dotenv默认的自动注入逻辑,改用手动解析的方式拿到配置对象。
基于dotenv的实现
dotenv暴露了parse方法,接收.env文件的文本内容,直接返回解析后的键值对对象,全程不会自动写入process.env,不会改动任何原有环境变量。
注意直接给process.env赋值对象会被Node.js强制转为字符串,需要用属性定义的方式挂载配置对象,才能支持嵌套属性访问:
const fs = require('fs') const dotenv = require('dotenv') const path = require('path') // 读取并解析.env文件,不触发自动注入 const envContent = fs.readFileSync(path.resolve(process.cwd(), '.env')) const specialValues = dotenv.parse(envContent) // 挂载到process.env下,避开自动类型转换 Object.defineProperty(process.env, 'specialValues', { value: specialValues, writable: true, enumerable: false, // 不会被环境变量遍历逻辑识别,不影响其他模块 configurable: true })
完成后直接通过process.env.specialValues.USERNAME就能访问.env中存储的配置值,原有process.env上的同名属性(比如你提到的USERNAME=xterm)完全不会被修改,其他模块的运行逻辑不受任何影响。
无依赖轻量替代
如果不想引入第三方库,几十行代码就能实现.env解析逻辑,满足基础场景需求:
const fs = require('fs') const path = require('path') function loadCustomEnv(envPath) { const fileContent = fs.readFileSync(envPath, 'utf-8') const config = {} fileContent.split(/\r?\n/).forEach(rawLine => { const line = rawLine.trim() // 跳过空行、注释行 if (!line || line.startsWith('#')) return const equalIndex = line.indexOf('=') if (equalIndex < 1) return const key = line.slice(0, equalIndex).trim() let val = line.slice(equalIndex + 1).trim() // 去除值首尾包裹的单/双引号 if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) { val = val.slice(1, -1) } config[key] = val }) return config } // 挂载逻辑和之前一致 const specialValues = loadCustomEnv(path.join(process.cwd(), '.env')) Object.defineProperty(process.env, 'specialValues', { value: specialValues, enumerable: false, writable: true, configurable: true })
注意事项
- 禁止直接写
process.env.specialValues = 配置对象,Node.js会自动将process.env的所有属性值转为字符串,最终得到的是[object Object],无法访问内部嵌套属性。 - 定义属性时将
enumerable设为false,可以避免这个自定义属性被Object.keys(process.env)、环境变量遍历逻辑识别到,不会干扰其他依赖原生环境变量的模块运行。
内容的提问来源于stack exchange,提问作者Aaron Meese
相关产品推荐
相关产品推荐

