app scaffold
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
# conti-retail-app
|
||||
|
||||
大陆马门店 App。Flutter + Melos 单仓多包。
|
||||
|
||||
架构约束全部来自相邻仓库 `conti-docs/` 的 01–14 号文档。**本仓库对这些文档的
|
||||
偏离,逐条记在 [SCAFFOLD-NOTES.md](SCAFFOLD-NOTES.md)**——那份文件是回写文档的
|
||||
依据,改动之前先看一眼。
|
||||
|
||||
---
|
||||
|
||||
## 怎么跑起来
|
||||
|
||||
三步。不要跳过第二步。
|
||||
|
||||
```bash
|
||||
# 0. 工具链(一次性)
|
||||
fvm use 3.44.9 # 或者保证 PATH 上的 flutter 就是 3.44.9
|
||||
dart pub global activate melos 8.2.2
|
||||
|
||||
# 1. 装依赖
|
||||
melos bootstrap
|
||||
|
||||
# 2. 生成代码(riverpod 的 *.g.dart 不入库,不跑这步全仓库编译不过)
|
||||
melos run gen
|
||||
|
||||
# 3. 跑起来
|
||||
cd app
|
||||
flutter run --flavor dev -t lib/main_dev.dart --dart-define-from-file=env/dev.json
|
||||
```
|
||||
|
||||
`--flavor` / `-t` / `--dart-define-from-file` **三个参数缺一不可**:
|
||||
|
||||
- 少了 `--dart-define-from-file`,`AppEnv.fromDartDefine` 会在启动瞬间抛错。
|
||||
这是故意的——带着空 baseUrl 跑起来,问题会在第一个请求 404 时才暴露。
|
||||
- 少了 `-t`,Flutter 会去找 `lib/main.dart`,本仓库没有这个文件。
|
||||
|
||||
VS Code / Android Studio 用户建议把三条 flavor 配进 `launch.json`。
|
||||
|
||||
## 环境与工具链版本
|
||||
|
||||
跑通时的实测版本,与 `pubspec.lock` 一致:
|
||||
|
||||
| | 版本 | 备注 |
|
||||
|---|---|---|
|
||||
| Flutter | 3.44.9 | `.fvmrc` 里锁着 |
|
||||
| Dart | 3.12.2 | **Flutter 自带的那个**,见下面的坑 |
|
||||
| Melos | 8.2.2 | 配置内联在根 `pubspec.yaml`,没有 `melos.yaml` |
|
||||
| flutter_riverpod | 3.3.2 | |
|
||||
| riverpod_annotation | 4.0.3 | |
|
||||
| riverpod_generator | 4.0.4 | |
|
||||
| build_runner | 2.15.1 | |
|
||||
| analyzer | 12.1.0 | |
|
||||
|
||||
> **riverpod 的版本被 `flutter_test` 卡着。** `flutter_test` pin 了
|
||||
> `test_api 0.7.11`,往上升 riverpod 会拉起不兼容的 `analyzer`,解析直接失败。
|
||||
> 想升级先确认这条链路,不要只看 pub.dev 上的最新版。
|
||||
|
||||
### 坑:机器上有两个 Dart SDK
|
||||
|
||||
如果你的 PATH 上装了独立的 Dart SDK(`dart --version` 不等于 3.12.2),那么
|
||||
|
||||
```bash
|
||||
dart run build_runner build # ← 会用错 SDK,报一堆看不懂的解析错误
|
||||
```
|
||||
|
||||
要显式用 Flutter 自带的那个:
|
||||
|
||||
```bash
|
||||
export FDART="$(dirname "$(which flutter)")/cache/dart-sdk/bin/dart"
|
||||
$FDART run build_runner build
|
||||
# fvm 用户:~/fvm/versions/stable/bin/cache/dart-sdk/bin/dart
|
||||
```
|
||||
|
||||
`melos run gen` 内部走的是 `dart run`,所以同样受影响。最省事的做法是让 PATH
|
||||
上只有 Flutter 自带的 Dart。
|
||||
|
||||
### 坑:melos 命令
|
||||
|
||||
pub cache 里只有 `melos.bat`,git-bash 下直接敲 `melos` 可能找不到。用:
|
||||
|
||||
```bash
|
||||
dart pub global run melos:melos <cmd>
|
||||
```
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
melos run gen # 代码生成(riverpod)
|
||||
melos run gen:watch # 开发期常驻
|
||||
melos run gen:pigeon # native_* 的 Pigeon 产物(产物入库)
|
||||
melos run analyze # flutter analyze --fatal-infos,含 riverpod_lint
|
||||
melos run format # dart format --set-exit-if-changed
|
||||
melos run test # flutter test --coverage
|
||||
```
|
||||
|
||||
`analyze` 带 `--fatal-infos`。不加等于没加 lint——绝大多数 riverpod_lint 规则
|
||||
报的是 info 级。
|
||||
|
||||
`riverpod_lint` 由 `flutter analyze` 直接执行(顶层 `plugins:` 映射),**不再
|
||||
需要 `custom_lint`**,也没有 `dart run custom_lint` 这一步。文档 03/14 写的还是
|
||||
旧方案,见 SCAFFOLD-NOTES §B。
|
||||
|
||||
## 包结构与依赖规则
|
||||
|
||||
```
|
||||
app/ 壳工程。唯一知道所有包的地方:环境注入、启动编排、路由聚合
|
||||
packages/
|
||||
core_foundation/ AppEnv / AppException 体系 / ApiCode ← 叶子包,谁都能依赖
|
||||
core_logging/ AppLogger / CrashReporter / 脱敏
|
||||
core_analytics/ Analytics 接口 + 事件常量表
|
||||
core_storage/ Prefs(KV)。Drift 暂缓,见 SCAFFOLD-NOTES
|
||||
core_auth/ AppSession 四态 / TokenStorage / SessionNotifier
|
||||
core_network/ dio + 4 个拦截器 + ApiClient
|
||||
core_router/ goRouterProvider / menuRouteMap / go_router re-export
|
||||
core_ui/ 主题 / AsyncValueView / ErrorPresenter
|
||||
core_webview/ UrlGuard / JSBridge / WebViewSession
|
||||
feature_auth/ 登录、选店
|
||||
feature_home/ 工作台
|
||||
native_scan/ Pigeon 扫码接口(原生实现待补)
|
||||
```
|
||||
|
||||
依赖规则(01):
|
||||
|
||||
- `feature_* → core_* / native_*`。**feature 之间禁止互相依赖**——两个 feature
|
||||
要共享东西,说明那个东西属于某个 core_*。
|
||||
- `core_* → core_*` 只允许三条边:`core_network → core_auth`、
|
||||
`core_router → core_auth`、`core_webview → core_auth`。外加所有包都可以依赖
|
||||
叶子包 `core_foundation`。
|
||||
- `native_* ` 只依赖 Flutter SDK 和 Pigeon 产物,**一个 core_* 都不依赖**。
|
||||
- feature 的 pubspec 里**不出现 `go_router`**:路由类型由 `core_router`
|
||||
re-export。
|
||||
|
||||
### 这些规则靠 `--fatal-infos` 守,不是靠编译器(实测结论)
|
||||
|
||||
直觉上会以为「没在 pubspec 里声明就 import 不到」。**在 Pub Workspace 里这是错的**:
|
||||
所有成员包共用根目录一份 `.dart_tool/package_config.json`,任何成员都能解析到
|
||||
任何其他成员。实测在 `feature_home` 里 import `feature_auth` 而不声明依赖:
|
||||
|
||||
```
|
||||
flutter test → All tests passed! ← 编译通过,跑得起来
|
||||
flutter analyze → info: depend_on_referenced_packages
|
||||
```
|
||||
|
||||
只有一条 **info**。所以:
|
||||
|
||||
> **`melos run analyze` 的 `--fatal-infos` 是这套包边界唯一的强制点。**
|
||||
> 谁把它从 CI 里拿掉,或者在某个包里 ignore 掉
|
||||
> `depend_on_referenced_packages`,边界当天就失效,而且没有任何别的信号。
|
||||
|
||||
想自己复现:在 `feature_home/lib/src/` 下扔一个 import `feature_auth` 的文件,
|
||||
`flutter test` 是绿的,`flutter analyze --fatal-infos` 是红的。
|
||||
|
||||
### 那些 `throw UnimplementedError('必须在 bootstrap 里 override')`
|
||||
|
||||
依赖规则会挡住一些**合理**的调用(比如 core_auth 想发 HTTP、core_webview 想
|
||||
换票)。这些地方一律用依赖反转解决:包内声明 `abstract interface` + 一个会抛错
|
||||
的 provider,实现落在 `app/lib/bootstrap.dart` 里 override 进去。
|
||||
|
||||
新增一个这样的端口时,**必须同时在 bootstrap 里接上**——它是运行期才炸的,
|
||||
编译器帮不了你。
|
||||
|
||||
## 待办 / 阻塞项
|
||||
|
||||
- **iOS flavor 未配置**:Scheme 和 Build Configuration 只能在 Xcode 里建,
|
||||
步骤见 [`app/ios/FLAVORS.md`](app/ios/FLAVORS.md)。目前没有 Mac 构建机。
|
||||
- **native_scan 没有原生实现**:Pigeon 接口和 Dart 侧齐了,Kotlin/Swift 侧是
|
||||
模板。现在调 `startScan` 会抛 `MissingPluginException`,属预期。
|
||||
- **神策 SDK 未采购**:`analyticsProvider` 是 `NoopAnalytics`。接入时注意必须在
|
||||
用户同意隐私政策之后再初始化。
|
||||
- **env/*.json 里全是占位域名**,`SENTRY_DSN` 全空,待运维确认。
|
||||
- **CI 镜像名未定**,`.gitlab-ci.yml` 里标了 TODO(ops)。
|
||||
Reference in New Issue
Block a user