.env 文件是一种简单而高效的方式,用于管理项目中的环境变量。通过 dotenv 库加载 .env 文件,可以在开发环境中方便地使用环境变量,同时通过 .gitignore 确保敏感信息的安全性。生产环境中建议直接使用系统环境变量以提高安全性和灵活性。
🤷♂️ 什么是配置,为什么要和代码分开存储
何谓配置:随部署环境(开发/测试/预发布staging/发布)变化的任何资源
- 连接数据库、Memcached和 其他后端服务的任何资源
- 访问外部服务(如 Amazon S3 或 OpenAI)的凭证
- 每份部署特有的配置,如域名等
配置不能当做代码常量!须严格和代码隔离。
有时,应用会将配置作为代码中的常量存储。这是违反十二要素应用原则的,十二要素要求严格分离配置与代码。配置在不同部署之间变化很大,而代码则不会。
判断应用是否已正确将所有配置从代码中分离出来的试金石是:代码库是否可以在任何时刻开源,而不会泄露任何凭证。
需要注意的是,“配置”的定义不包括内部应用配置,如内部代码模块之间的连接方式。这种类型的配置在不同部署之间不会变化,因此最好在代码中完成。
🔍 设置和读取 env 文件
Node.js 为例。在项目的根目录下创建一个名为 .env 的文件。使用 dotenv 库加载 .env 文件中的环境变量。
.env
NUXT_OPENAI_API_KEY=xxxxxxx
KV_URL=XXXXXXXX
KV_REST_API_URL=XXXXXXXX
KV_REST_API_TOKEN=XXXXXXXX
KV_REST_API_READ_ONLY_TOKEN=XXXXXXXX
读取
require('dotenv').config();
console.log(process.env) // 测试后删除
这样 .env 文件中的变量会被加载到 process.env 对象中。
🔒 保护敏感信息
一般我们会将敏感信息存储在 env 文件内,如何保证不泄露?
原则:切勿在非开发环境中使用 .env 文件。
1 将 .env 文件添加到 .gitignore 中,避免其被提交到版本控制系统:
env 文件被添加到 .gitignore 文件,那代码运行时候比如生产环境下不就拿不到 env 内的配置了吗?
2 在生产环境中,通常不会直接使用 .env 文件。
应该使用系统环境变量或如果使用 CI/CD 工具(如 GitLab CI、Jenkins 等),可以在这些工具的配置中设置环境变量。 这些变量会在部署时自动注入到应用程序中,而无需依赖 .env 文件,详见使用原生平台变量存储 。
foo=bar npm run build
dotenv 该库保证环境变量优先于 .env 配置,故即使生产环境没有 env 文件,部署后也无需修改代码。
// 该代码无需变化仍然能读取到生产环境的环境变量
require('dotenv').config();
3. 为了让开发者可以知道如何配置 env,一般都会存在一份 .env.example
为了兼顾安全和开发体验,一般我们会将一份脱敏的 env 文件放到 git 仓库。
开发者将其重命名为 .env 即可使用。
4. env.vault 更安全的 env 文件
这个方案已经被很多语言支持,比如 Python、Rust 以及 Node.js 本身详见 What is a .env.vault file ,此处不表。
🧪 Node.js 原生支持 env 文件,但现仍不是 dotenv 卸甲归田之时
Node.js(2025-3-3)env 开发进展:
- v20.6.0 实验性支持
- v20.12.0 值支持多行
- v23.9.0(最新版本)积极开发中
Node.js@v20.6.0 开始原生支持 env 文件,甚至可指定多个文件:node --env-file=.env --env-file=.development.env app.js,合并策略同对象解构。和 dotenv 同理,环境变量优先于 env 文件。其次默认加载不存在的文件会报错,但可通过 --env-file-if-exists flag 抑制。
相较 dotenv 这个下载量巨大的社区包,Node.js 暂不支持
来自社区的声音
这些特性也许会是 Node.js 官方未来的 roadmap。