SuperAPI AI 工具集

app-variants-and-environment

部署与运维

查看项目

更新于 10-18 18:05

技能介绍

用途

该技能解决 Expo 应用的多环境构建问题:一个应用需要同时产出 development(开发客户端)、preview(内部测试)和 production(商店发布)三种变体,由 APP_VARIANT 选择。每个变体可并排安装在同一台设备上,并明确标识自身身份。技能同时确保 EXPO_PUBLIC_* 值被当作公开信息处理,密钥保留在 EAS 或 CI 中,测试专用代码不会进入商店包。

主要能力

  • 统一变体解析:app.config.ts 通过 src/config/app-variant.ts 中的 resolveAppVariant(process.env) 决定变体,仅接受 development、preview、production;未知名称抛错;APP_VARIANT 与 EXPO_PUBLIC_APP_VARIANT 必须相等;两者均未设置时,本地开发视为 development,而在生产包(NODE_ENV=production:expo export、eas update、expo start --no-dev)或 EAS Build(EAS_BUILD=true)中抛错。
  • 变体身份隔离:production 保留商店 id;development 和 preview 在 iOS bundle identifier 与 Android package 后追加 .dev 和 .preview;每个变体拥有独立名称(如 Tasks (Dev)、Tasks (Preview))、图标文件和 URL scheme;dev client 生成的 exp+<slug> scheme 仅用于 development。
  • EAS 构建配置:每个 EAS build profile 需两次命名变体(env.APP_VARIANT 与 env.EXPO_PUBLIC_APP_VARIANT)并指定一次 environment;仅 development 设置 developmentClient;共享 base profile 不命名变体、环境或 developmentClient。
  • 公开值与密钥管理:EXPO_PUBLIC_* 由 Metro 内联进 JS bundle,任何人可读,因此不得包含 SECRET、TOKEN、PASSWORD、私钥、支付密钥或付费/LLM API 密钥;应用应调用持有密钥的服务器(如 Expo Router API route);设计上公开的密钥(如限制到应用 id 的 Maps key、Stripe publishable key)放入 publicEnvAllow 并注明原因。
  • 环境读取集中化:仅 src/config/ 读取 process.env,且仅以 process.env.EXPO_PUBLIC_NAME 点访问形式;变体通过 currentAppVariant() 获取,不通过 Constants.expoConfig.extra 或 DEV。
  • 测试代码剥离:测试专用代码放在单个三元表达式中,使用 process.env.EXPO_PUBLIC_APP_VARIANT === 'production' 字面量比较,不能藏在导入常量、辅助函数、DEV、NODE_ENV 或 if 块后。
  • Metro 缓存键:metro.config.js 的 cacheVersion 由所有 EXPO_PUBLIC_* 名称和值生成,随公开值变化并按变体区分。
  • 校验脚本:check-variants.mjs、check-env.mjs、check-variant-bundle.mjs 分别校验配置、源码与文件、导出 bundle;make-variant-icons.mjs 生成带标记的变体图标。

使用方式

  1. 阅读 references/variant-matrix.md 确定三个变体的 id、名称、图标、scheme 及需要注册 id 的服务。
  2. 先保存 production 配置到 dist/config-before.json,再合并模板:复制 templates/src/config/app-variant.ts 及其测试、current-app-variant.ts 及其测试、env.d.ts;基于 templates/app.config.ts 构建 app.config.ts,迁移旧 app.json 中的 owner、version、updates.url、runtimeVersion、extra.eas.projectId、插件及选项、ios.infoPlist 用法字符串、android.permissions、颜色、splash 等。
  3. 将图标移入 assets/icons/production/,运行 node ${CLAUDE_SKILL_DIR}/scripts/make-variant-icons.mjs . 生成 development 和 preview 的带标记副本。
  4. 复制 templates/metro.config.js 及相关脚本,合并 templates/eas.json 的三个 build profile,复制 .env.example。
  5. 运行 npx expo install expo-dev-client expo-splash-screen。
  6. 保存 dist/config-after.json 并与 before 对比,确认仅图标路径、expo-dev-client 插件和旧 extra.appVariant 变化,然后删除 app.json。
  7. 将所有读取路由到 src/config/,用 currentAppVariant() 替换变体检查。
  8. 按 references/secrets.md 放置密钥,向开发者提供 eas env:set 命令(构建时密钥用 secret 可见性,API route 密钥用 sensitive,APP_VARIANT 与 EXPO_PUBLIC_APP_VARIANT 用 plain text)。
  9. 用字面量比较门控测试代码,运行 typecheck、eslint、jest,检查各变体配置与 prebuild,运行校验脚本直至 RESULT: PASS。
  10. 变体、门控、metro.config.js 或变量变更后,连续导出 development 与 production 到 dist/variant-proof/ 并用 check-variant-bundle.mjs 验证剥离。

适用场景

需要为 Expo / React Native 应用建立多环境构建体系、隔离测试代码与密钥、并确保商店包不含测试代码和敏感信息的项目。

限制

  • 该技能依赖 Expo SDK 57 的 Metro 行为(仅折叠同一表达式中的字面量)。
  • 密钥创建、修改、删除及轮换需在开发者 Expo 账户中执行,操作前需停止并询问。
  • EAS Hosting 无法部署 secret 可见性的变量。
  • 未提供 eas.json 时,check-variants 会打印 SKIP,需由 eas-build-and-submit 创建。
  • 具体价格、平台支持范围等资料未提供。