128 lines
5.3 KiB
Markdown
128 lines
5.3 KiB
Markdown
# 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/产品层面接受系统限制,并通过缓存提升体验
|
||
|