Egg 运行环境Server Env机制详解EGG_SERVER_ENV、config/env 与 NODE_ENV 的完整使用指南【免费下载链接】egg Born to build better enterprise frameworks and apps with Node.js Koa. https://307.run/eggcode项目地址: https://gitcode.com/gh_mirrors/eg/egg导读Egg 框架将“运行环境Server Env”作为应用自适应的核心机制一个 Web 应用本身应该是无状态的并拥有根据运行环境设置自身的能力——通过EGG_SERVER_ENV环境变量或config/env文件即可精确指定环境框架会自动加载对应的config.{env}.js配置、切换日志级别并激活对应插件。本文围绕 site/docs/zh-CN/basics/env.md 展开结合仓库源码packages/core/src/loader/egg_loader.ts、packages/core/test/loader/get_server_env.test.ts、packages/egg/src/config/config.default.ts深入讲解环境指定的三种方式、优先级、与NODE_ENV的映射关系、自定义环境以及 Egg 与 Koa 在环境判断上的差异。读完本文你将能正确地在本地、测试、预发SIT和生产环境中部署 Egg 应用并理解环境变量在配置加载、日志与插件开关中的实际影响。一、为什么需要区分运行环境Egg 应用在不同环境下有不同的行为需求本地开发local开启完整调试输出、热重载日志打到控制台单元测试unittest使用内存数据库、禁用部分中间件、输出 WARN 以上日志生产prod隐藏详细错误、禁用控制台日志、加载最优配置。框架通过一个单一的运行环境标识serverEnv驱动配置加载、插件启用、日志级别等全部行为。从源码看EggLoader在初始化时首先解析出serverEnv再据此构造appInfo并加载配置// packages/core/src/loader/egg_loader.ts#L160-L173 this.serverEnv this.getServerEnv(); debug(Loaded serverEnv %j, this.serverEnv); ... this.appInfo this.getAppInfo();而appInfo.env会直接注入到config.default.js中成为app.config.env// packages/egg/src/config/config.default.ts#L19 env: appInfo.env,二、两种指定运行环境的方式方式一通过config/env文件指定在应用根目录的config/env文件中写入环境名文件内容会被去除首尾空白后作为运行环境// config/env prod该文件一般由构建工具CI/CD 流水线、发布系统在部署时生成用于固定目标环境的身份。优点是部署系统只需落盘一个文件无需改动进程启动参数。方式二通过EGG_SERVER_ENV环境变量指定相比写文件环境变量更灵活适合手工运维与容器编排Docker/K8s场景。比如在生产环境启动应用EGG_SERVER_ENVprod npm start三、环境解析的完整优先级源码级框架解析serverEnv的实现位于EggLoader#getServerEnv()// packages/core/src/loader/egg_loader.ts#L200-L226 protected getServerEnv(): string { let serverEnv this.options.env; const envPath path.join(this.options.baseDir, config/env); if (!serverEnv fs.existsSync(envPath)) { serverEnv fs.readFileSync(envPath, utf8).trim(); } if (!serverEnv process.env.EGG_SERVER_ENV) { serverEnv process.env.EGG_SERVER_ENV; } if (serverEnv) { serverEnv serverEnv.trim(); } else { if (process.env.NODE_ENV test) { serverEnv unittest; } else if (process.env.NODE_ENV production) { serverEnv prod; } else { serverEnv local; } } return serverEnv; }由此可以得到明确的优先级顺序options.env编程式传入如单元测试中createApp(dir, { env: prod })config/env文件$baseDir/config/envEGG_SERVER_ENV环境变量以上均未指定时回退到NODE_ENV映射test → unittest、production → prod、其他包括不设置→local。其中config/env文件的优先级高于EGG_SERVER_ENV这一点被测试用例显式验证// packages/core/test/loader/get_server_env.test.ts#L41-L57 it(should get from config/env, () { mm(process.env, NODE_ENV, production); mm(process.env, EGG_SERVER_ENV, test); // 环境变量被覆盖 app createApp(serverenv-file); // 夹具中存在 config/env assert.equal(app.loader.serverEnv, prod); }); it(should use options.env first, () { mm(process.env, EGG_SERVER_ENV, test); app createApp(serverenv-file, { env: development }); assert.equal(app.loader.serverEnv, development); });注意环境值会被trim()处理因此EGG_SERVER_ENVtest 这类带尾随空格的写法也能被正确解析见 get_server_env.test.ts。四、应用内获取运行环境框架将当前运行环境暴露在app.config.env上// 在 Controller / Service 中 module.exports (app) { app.get(/, async (ctx) { ctx.body 当前运行环境: ${app.config.env}; }); };其数据链路为serverEnv → appInfo.env → config.default.js 中的 env 配置项 → app.config.env。配置内部如config.default.js中通过appInfo.env分支处理逻辑也能直接使用它。五、运行环境相关的配置加载不同的运行环境对应不同的配置文件规则是框架会先加载config.default.js通用配置再加载config.{env}.js环境专属配置后者通过深度合并覆盖前者// packages/core/src/loader/egg_loader.ts#L1091-L1101 async #preloadAppConfig(): PromiseRecordstring, any { const names [config.default, config.${this.serverEnv}]; const target: Recordstring, any {}; for (const filename of names) { const config await this.#loadConfig(this.options.baseDir, filename, undefined, app); ... extend(true, target, config); } return target; }因此设置EGG_SERVER_ENVsit时框架会加载config/config.sit.js设置EGG_SERVER_ENVprod时加载config/config.prod.js未显式设置时按第三节的映射回退。此外运行环境还驱动插件开关config/plugin.js中每个插件都支持env数组字段用于限定仅在特定环境下启用如env: [local, unittest]源码见 egg_loader.ts。日志行为同样随环境变化config.default.ts中consoleLevel在local下默认为INFO、unittest下为WARN、其余环境为NONE见 packages/egg/src/config/config.default.ts且disableConsoleAfterReady在非 local/unittest 环境默认为true同上 L284。完整的配置编写与加载机制请阅读 Config 配置。六、EGG_SERVER_ENV与NODE_ENV的区别很多 Node.js 应用习惯用NODE_ENV区分环境但EGG_SERVER_ENV划分得更精细。两者的职责不同NODE_ENV是 Node.js 生态的通用约定同时被 npm 使用部署时通常不会安装devDependencies因此服务器环境的NODE_ENV应保持为productionEGG_SERVER_ENV是 Egg 专有的精确环境标识可表达本地开发、单元测试、集成测试SIT、预发staging、生产等更多粒度。一般的项目开发流程包括本地开发、测试、生产等环境除本地开发与测试外其余均可归为服务器环境其NODE_ENV应为production。框架默认支持的运行环境及映射关系未指定EGG_SERVER_ENV时根据NODE_ENV匹配如下NODE_ENVEGG_SERVER_ENV说明不设置local本地开发环境testunittest单元测试productionprod生产环境例如当NODE_ENV为production而EGG_SERVER_ENV未指定时框架会将EGG_SERVER_ENV设置成prod。上述映射逻辑与测试用例一一对应get_server_env.test.tsit(should use unittest when NODE_ENV test, () { mm(process.env, NODE_ENV, test); assert.equal(app.loader.serverEnv, unittest); }); it(should use prod when NODE_ENV production, () { mm(process.env, NODE_ENV, production); assert.equal(app.loader.serverEnv, prod); }); it(should use local when NODE_ENV is other, () { mm(process.env, NODE_ENV, development); assert.equal(app.loader.serverEnv, local); });七、自定义环境以 SIT 集成测试为例Egg 支持开发者按实际需要自定义环境无需修改框架代码。假如你需要在开发流程中加入 SIT 集成测试环境只需两步设置环境变量EGG_SERVER_ENVsit建议同时设置NODE_ENVproduction因为 SIT 属于服务器环境npm 不会安装 devDependencies。NODE_ENVproduction EGG_SERVER_ENVsit npm start启动后框架会加载config/config.sit.js配置文件同时仍先加载config.default.js作为基础将运行时环境的app.config.env设为sit若在config/plugin.js的插件声明中配置了env: [sit]则仅在该环境下启用对应插件。自定义环境同样适用于config/env文件方式将文件内容写为sit即可获得相同效果。八、与 Koa 的区别在 Koa 中通过app.env判断运行环境其默认值为process.env.NODE_ENV。而在 Egg及基于 Egg 的框架中配置统一放置于app.config因此需要通过app.config.env来区分环境不再使用app.env。这一点在源码注释中也有体现AppInfo#env明确标注为 “The environment of the application,its not NODE_ENV”并给出其取值来源顺序config/env文件 →EGG_SERVER_ENV→NODE_ENV见 packages/core/src/loader/egg_loader.ts#L290-L307。九、最佳实践小结本地开发无需任何设置默认local若需临时验证 prod 配置可用EGG_SERVER_ENVprod npm start单元测试运行测试工具时NODE_ENVtest自动映射为unittest测试框架如 egg 官方测试工具也支持通过options.env精确指定部署流水线推荐由构建工具在发布目录写入config/env文件内容如prod、sit或由编排平台注入EGG_SERVER_ENV并保证NODE_ENVproduction插件与日志善用插件声明中的env数组控制环境启用范围并留意日志级别会随环境自动调整切忌不要在业务代码里依赖process.env.NODE_ENV或 Koa 的app.env判断 Egg 环境统一使用app.config.env。【免费下载链接】egg Born to build better enterprise frameworks and apps with Node.js Koa. https://307.run/eggcode项目地址: https://gitcode.com/gh_mirrors/eg/egg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
