多环境配置与密钥管理实践
Created on
前言
当项目进入多环境阶段(开发/测试/预发/生产),最容易出问题的不是代码,而是配置与密钥管理。API Key、推送 AppKey、地图服务、归因 SDK、广告 ID,都可能因为配置混乱而导致线上故障。
本文结合真实项目实践,给出一套可落地的配置分层与密钥管理方案,重点解决“可切换、可追溯、可安全交付”。
设计目标
- 环境切换清晰且一致
- 配置来源单一,可追踪
- 密钥不进仓库
- 构建与运行时行为一致
配置分层模型
建议把配置分成三层:
- 编译期配置:决定原生工程与打包结果
- 运行时配置:决定业务行为与服务地址
- 构建系统配置:决定环境变量注入与密钥存储
这三层需要独立又可组合,避免“某个 .env 控制一切”的混乱。
编译期: app.config.ts + Config Plugin
编译期配置影响原生工程,必须集中在 app.config.ts 中完成,并通过 Config Plugin 统一注入。典型例子:
- 推送 AppKey/Channel
- 地图 SDK Key
- 深度链接 Scheme
推荐用环境变量驱动:
[
"@repo/push-notification/plugin",
{
appKey: process.env.EXPO_PUBLIC_JPUSH_APPKEY,
channel: process.env.EXPO_PUBLIC_JPUSH_CHANNEL,
},
];
这样能确保 prebuild 与 EAS Build 一致,同时避免硬编码。
运行时: EXPOPUBLIC 与 config/extra
运行时配置用于 JS 逻辑,推荐统一走 EXPO_PUBLIC_ 前缀,再由 app.config.ts 注入 extra:
extra: {
apiBaseUrl: process.env.EXPO_PUBLIC_API_BASE_URL,
mapProvider: process.env.EXPO_PUBLIC_MAP_PROVIDER,
},
这样可以在运行时通过 expo-constants 读取,且不会与原生配置混用。
构建系统: .env + EAS Secrets
推荐两套来源:
- 本地开发:
.env或.env.local - CI/EAS: secrets 注入(不进仓库)
原则是“密钥只进入构建环境,不进入仓库”。
环境切换策略
建议通过单一环境变量控制环境,例如:
EXPO_PUBLIC_APP_ENV=staging
然后在 app.config.ts 里映射不同配置:
const env = process.env.EXPO_PUBLIC_APP_ENV || "dev";
const apiBaseUrl =
env === "prod" ? "https://api.xxx.com" : "https://staging.xxx.com";
这样能保证切换是“显式的”,避免隐式配置导致混乱。
密钥命名规范
推荐统一前缀与责任归属:
- EXPO_PUBLIC_JPUSH_APPKEY
- EXPO_PUBLIC_GAODE_IOS_API_KEY
- EXPO_PUBLIC_GOOGLE_MAPS_KEY
- EXPO_PUBLIC_OPENINSTALL_APPKEY
命名越明确,排错越快。
常见坑
- 将密钥直接写入
app.config.ts - 在多个文件里重复读取环境变量
- 用同一个 Key 覆盖多环境
- 忘记同步 EAS Secrets 与本地 .env
小结
多环境配置的核心是“分层与一致性”。只要编译期配置集中在 Config Plugin,运行时配置走统一的 extra,密钥通过构建系统注入,就能最大程度降低配置事故,让环境切换变成日常操作而不是高风险动作。