我最早写这篇文章时,关注点很小:NodeJS 项目里怎么在 VSCode 调试时配置环境变量。
那时的需求也很直接。
项目里用
process.env 读取配置,生产环境可以直接在服务器或部署平台设置变量,但本地调试时,我不想为了测试一个参数就去改操作系统环境变量。所以我开始研究 WebStorm 和 VSCode 里怎么给某一次运行传入环境变量。
现在回头看,这其实不只是一个 IDE 配置技巧。
它背后是一个很重要的工程习惯:不同环境的配置要有边界。
我为什么关心环境变量
很多项目早期都会把配置写得很随意。
开发环境一个值,测试环境一个值,生产环境一个值。刚开始只有自己用,直接写在代码里好像也能跑。
但一旦项目变复杂,问题就会出现:
- 本地调试误连生产服务;
- 测试 token 被提交到代码仓库;
- 不同同事的本地配置互相污染;
- 部署平台和本地启动方式不一致;
- 问题复现时说不清当时用了哪些变量。
所以我现在看环境变量,不只是看它能不能传进去。
我会先问:这个配置属于哪个环境?它能不能被复现?它会不会泄露?它有没有被写进不该写的地方?
本地调试的核心目标
本地环境变量的目标不是让配置更复杂,而是让每一次启动更清楚。
比如一个 NodeJS 项目可能会读取:
NODE_ENV
NOTION_PAGE_ID
CUSTOM_PARAMS
NEXT_PUBLIC_*
- 数据库连接参数
- 第三方 API key
其中有些可以公开,有些不该进仓库,有些只用于本地测试。
如果全部混在一起,后面很难排查。
我更喜欢把本地调试理解成一次“带参数的实验”。
这次实验用了哪些变量,启动了哪个命令,工作目录是什么,都应该能被
launch.json 或脚本清楚表达。WebStorm 的路径
JetBrains 系列 IDE 在运行配置里设置环境变量比较直观。
我会这样理解它:
- 打开运行配置;
- 找到对应的 Node 或 npm/yarn 启动项;
- 在 Environment variables 中添加本次运行需要的变量;
- 保存后用这个配置启动项目。
这样做的好处是,变量只在当前运行配置中生效,不会污染整个系统。
它适合个人调试,也适合为不同启动场景保存多套配置。
比如:
- 本地普通开发;
- 连接测试数据库;
- 测试某个 Notion 页面;
- 临时打开某个 feature flag。
VSCode 的路径
VSCode 通常通过
.vscode/launch.json 管理调试配置。一个典型配置可以这样写:
这段配置表达的是:用
yarn dev 启动项目,并在这次进程里注入 env 下的变量。我关心的不是这段 JSON 本身,而是它带来的清晰性。
当我按这个配置启动时,我知道:
- 命令是什么;
- 工作目录在哪里;
- 哪些变量被传入;
- 这些变量只影响当前调试进程。
这比在系统里永久设置变量更可控。
我会怎么组织本地配置
如果是个人项目,我会保持简单。
可以把非敏感示例写进
launch.json,把真实密钥放进 .env.local 或部署平台环境变量。如果是团队项目,我会更谨慎:
- 提交
.env.example,说明需要哪些变量;
- 不提交真实
.env;
- 在 README 里写清启动方式;
- 对生产变量做最小权限;
- 对调试配置和部署配置分开管理。
有些变量可以放进代码仓库,比如公开的站点名称、前端展示开关。
有些变量不该进仓库,比如 token、数据库密码、私有 API key。
判断标准很简单:如果这个值泄露出去会带来权限、费用、数据或账号风险,就不要写进可公开的文件。
这件事对我后来的影响
后来我做 NotionNext、Cloudflare、Vercel、个人博客、AI 工具和各种小项目时,越来越明显感受到:环境变量管理是小项目变成可维护项目的早期分界线。
一个项目能不能交给别人跑,能不能部署到线上,能不能在出问题时复现,很多时候都取决于这些看似细小的配置是否清楚。
所以我会把环境变量当成项目契约的一部分。
代码告诉你系统怎么运行。
环境变量告诉你系统在哪个环境、以什么身份、连接哪些外部资源运行。
两者分开,项目才容易维护。
我会如何处理边界
这里有几个边界我会一直保留。
第一,不把真实密钥写进文章示例。
文章里的变量值只做演示,不应该复制真实 token。
第二,不把生产配置放进本地调试文件。
除非非常明确,否则本地调试应连接测试资源,避免误操作线上。
第三,不让配置散落在太多地方。
如果一个项目同时依赖系统变量、IDE 配置、
.env、部署平台变量和脚本参数,就要写清优先级,否则后面会很难排查。第四,配置要能被新接手的人理解。
一个好的本地开发配置,不应该只有作者自己知道怎么跑。
写在最后
VSCode 调试 NodeJS 环境变量,看起来只是一个很小的开发技巧。
但我现在更愿意把它看成工程边界训练。
本地是本地,测试是测试,生产是生产。
示例是示例,密钥是密钥。
代码负责逻辑,配置负责环境。
把这些边界分清楚,项目才不会在变大以后靠记忆运行。
这类小习惯不显眼,但它们会慢慢决定一个项目是否可复现、可交接、可部署。
Loading...




