# Client Bootstrap(技术计划) ## 1. 计划目标 基于 `spec.md` 的约束,落地一套可执行的客户端工程初始化方案,保证: - 开发者可本地启动与联调 - dev/prod 环境区分清晰 - i18n 支持 CN/EN/ES/PT/TC 并支持动态切换 - 目录结构标准化,可持续扩展 - EAS Build iOS 打包流程可执行 ## 2. 默认技术决策(本计划采用) - **Node.js**:建议 **20.x LTS**(最低 **18.x LTS**) - **包管理器**:pnpm(建议 **9.x**,最低 **8.x**) - **路由**:优先采用 `expo-router`(使用 `app/` 目录) - 若项目已使用 React Navigation,则保留 `src/navigation/` + `src/screens/` 的方案(见“可替代方案”) - **i18n**:`i18next` + `react-i18next` + `expo-localization` - **环境变量**:`.env.dev` / `.env.prod` + `EXPO_PUBLIC_` 前缀 - **网络层**:统一封装 `src/services/`(Axios 或 Fetch 二选一,先按 Axios 预留结构) - **状态管理**:Zustand(与现有 `spec.md` 一致) ## 3. 目录与模块规划 ### 3.1 顶层目录(目标态) - `app/`:路由入口(expo-router) - `src/`:业务代码 - `src/features/`:按功能域拆分(push/widget/cards) - `src/services/`:API 封装 - `src/store/`:状态管理 - `src/i18n/`:多语言资源与初始化 - `src/components/`、`src/hooks/`、`src/utils/`、`src/constants/`、`src/types/` - `assets/`:静态资源 - `app.json` 或 `app.config.ts`:Expo 配置与环境区分入口 - `eas.json`:EAS 配置(如启用) ### 3.2 关键模块拆分 - **i18n 模块**(`src/i18n/`) - `index.ts`:初始化(默认语言、回退语言、资源注册、与系统语言对齐) - `locales/*.json`:`zh-CN/en/es/pt/zh-TW` 五份资源 - (可选)`types.ts`:语言码类型与 key 约束 - **Push 模块**(`src/features/push/`) - 权限申请 - Token 获取与上报(接口对齐点在联调阶段确认) - **Widget 模块**(`src/features/widget/`) - 数据读取与缓存策略(先定义接口与缓存层,再落地 iOS 扩展实现) - **Cards 模块**(`src/features/cards/`) - 卡片滑动交互组件与数据模型 ## 4. 环境区分与配置计划 ### 4.1 环境变量与模板 - 提供 `.env.example`(至少包含 `EXPO_PUBLIC_API_BASE_URL`、`EXPO_PUBLIC_ENV`) - 本地开发使用 `.env.dev`,生产构建使用 `.env.prod` - README 明确: - 真机联调时 `localhost` 替换为局域网 IP - 环境变量不入库 ### 4.2 Bundle ID 与构建标识 - dev:`com.damer.mindfulness.dev` - prod:`com.damer.mindfulness` - 在 `eas.json` 中按 profile 区分环境变量注入与 bundle id(当工程文件落地后执行) ## 5. 多语言(i18n)落地计划 ### 5.1 语言码与策略 - 支持:`zh-CN` / `en` / `es` / `pt` / `zh-TW` - 默认:优先使用用户当前**设备语言**(在支持列表内时生效) - 回退:设备语言不在支持列表时,回退到 `zh-CN`(或团队指定的默认语言) ### 5.2 动态切换与持久化 - 提供“语言设置”入口(后续 UI 落地),允许用户手动切换语言 - 切换语言后写入本地存储(例如 AsyncStorage) - App 启动时语言选择优先级: - ① 用户设置(若存在) - ② 设备语言(在支持列表内) - ③ 默认回退(`zh-CN` 或团队指定默认) ### 5.3 文案规范 - key 点分层:`common.*`、`push.*`、`cards.*`、`widget.*` - 插值:`{{name}}` 等形式统一 - 禁止代码内拼接长句(降低翻译成本) ## 6. 推送与小组件(一期能力)计划 ### 6.1 推送 - 客户端:权限 -> token -> 上报 - 后端:保存 token -> 定时任务 -> 推送内容配置 - 联调产出:token 上报接口、字段、鉴权、错误码约定(后续任务阶段细化) ### 6.2 小组件 - 先定义“数据模型 + 缓存策略 + 刷新策略”的规范 - 明确限制:刷新频率受 iOS 系统控制,文档中强调体验目标为“尽力而为” ## 7. 执行步骤(落地顺序) 1. **补齐客户端 README**:确保启动/环境/i18n/目录/EAS 指引完整(已完成基础版本) 2. **初始化 Expo 工程(如尚未提交)**:生成 `package.json`、`app.json/app.config.*`、`assets/` 等 3. **建立标准目录结构**:创建 `app/`、`src/` 与各子目录 4. **接入 i18n 基座**:完成语言码、资源文件、初始化与切换策略 5. **接入环境变量读取**:确保 dev/prod 可影响 API Base URL 6. **预留 push/widget/cards 的模块骨架**:先放类型与接口占位,等待业务实现 7. **EAS 配置与 iOS 构建跑通**:编写 `eas.json` 并验证 development profile 构建链路 ## 8. 可替代方案(不影响目标的变体) - **路由不使用 expo-router**:使用 React Navigation - 目录:`src/navigation/` + `src/screens/` - 仍保留 `src/features/`、`src/services/`、`src/i18n/` 等不变 - **网络层使用 Fetch**:保持 `src/services/` 统一封装,替换实现即可 ## 9. 风险与回滚策略 - **真机联调失败**:优先排查局域网 IP、代理/防火墙、后端端口映射;必要时使用内网穿透 - **推送配置复杂**:先在 dev profile 跑通 token->推送最小闭环,再扩展定时策略 - **小组件刷新不稳定**:在 UI/产品层面接受系统限制,并通过缓存提升体验