本手册保留当前仍有操作价值的 Mobile 调试规则。更长的历史排障复盘已压缩到 blog-archive.md。
Expo env 加载优先级通常会让 .env.local 覆盖 .env。本地开发如果 .env.local 指向线上地址,会导致真机请求误走线上。
建议:本地开发只保留明确用途的 .env,生产/预览构建变量放到 eas.json 或 EAS secret。
npx expo start --no-dev --minify 可能触发 production 环境变量加载。
建议:不要依赖本地 .env.production 做 EAS 生产配置,生产变量统一由 eas.json / EAS secret 管理。
真机上的 localhost 指向手机自身,不是开发机。
建议:本地 AI 或 Web 服务调试时使用局域网 IP,例如 http://192.168.x.x:3001,并确认手机和电脑在同一网络。
常见原因:
- 手机 Expo Go / Dev Client 还连着旧的 Metro server。
- Metro 或 Expo Go 缓存了旧 bundle。
- 电脑上启动的是另一个目录或另一个终端里的 dev server。
- 使用了已安装的 preview/dev build,而不是当前二维码对应的开发会话。
处理顺序:
- 停掉所有正在运行的 Expo/Metro 进程。
- 在仓库根目录运行
pnpm --filter @notion/mobile start:clear,或本地 AI 调试时运行pnpm --filter @notion/mobile dev:local:clear。 - 手机端关闭 Expo Go / Dev Client 后重新打开,再扫新的二维码。
- 如果仍是旧页面,清理 Expo Go 缓存或卸载重装当前 dev build。
- 确认终端输出的项目路径是
apps/mobile,不要扫到其他项目的 Metro 二维码。
expo-router 中如果在 navigator 挂载前导航,原生端可能白屏。
建议:优先在根 _layout.tsx 的 Stack 上配置 initialRouteName,避免入口页立即重定向。
expo-router 会扫描 app/ 下文件。业务源码不应放在 app/src 里。
建议:移动端业务源码放到 apps/mobile/src 或明确不被 router 扫描的位置,app/ 只保留路由。
useAuth() 未加载完成时不要直接返回 null。
建议:显示 loading 状态,避免真机白屏无法判断是认证、路由还是渲染问题。
排查顺序:
- 确认请求 URL 是局域网、本地服务还是线上服务。
- 查看服务端是否有请求日志;无日志通常说明请求未到服务端或被平台路由拦截。
- 检查
.vercel.app等域名在当前网络下是否可访问。 - Native 端不要假设
ReadableStream行为和 Web 一致,必要时用response.text()读取完整 SSE 文本再解析。
移动端图片上传走 Web /api/upload-image。本地调试时需要同时确认两个地址:
EXPO_PUBLIC_WEB_AGENT_URL:Web Agent 服务地址,当前应指向 Web 应用。EXPO_PUBLIC_WEB_URL:图片上传、预览链接等 Web API 地址。
如果浏览器控制台出现 Request header field authorization is not allowed by Access-Control-Allow-Headers,说明当前请求打到的 Web API 还没允许 Authorization 预检头,或者请求打到了尚未部署新代码的线上地址。
本地调试推荐:
# 终端 1:让 Web 服务监听局域网
pnpm --filter @notion/web exec next dev -H 0.0.0.0 -p 3000
# 终端 2:Mobile 同时指向本地 Web/AI 服务
EXPO_PUBLIC_WEB_URL=http://<电脑局域网IP>:3000 \
EXPO_PUBLIC_WEB_AGENT_URL=http://<电脑局域网IP>:3000 \
pnpm --filter @notion/mobile start:clear如果 OPTIONS 正常但 POST 500/504,浏览器可能仍显示 CORS 类错误。
建议:优先看实际 POST 状态码、服务端日志和上游首包时间。
前置条件:
EXPO_PUBLIC_WEB_AGENT_URL指向可被真机访问的 Web 应用地址。- 目标文档包含标题、正文段落和至少一次未等待防抖保存的编辑。
检查步骤:
- 打开文档详情页,修改标题或正文。
- 立即点击右上角 AI 图标打开 Chat。
- 发送“总结当前文档”。
- 确认 Agent 能读取当前文档内容,且结果包含刚刚编辑但可能尚未防抖保存的内容。
通过标准:
- 服务端
/api/agent/stream收到currentDocument.id/title/content。 - Mobile 端能展示流式文本、tool event 和来源。
- 从来源跳转回文档不崩溃。
前置条件:
- 真机已授予相册权限。
- Web
/api/upload-image和 EdgeStore 配置可用。
检查步骤:
- 打开文档详情页,点击“插入图片”。
- 选择一张合法图片,等待上传和保存完成。
- 退出文档后重新进入。
- 断网后再次点击“插入图片”。
通过标准:
- 合法图片能插入正文并持久化,重开文档后仍可渲染。
- 插入后立即返回页面,不应丢失图片节点。
- 断网时不会长时间挂起,能给出失败提示。
- 权限拒绝、用户取消、上传失败不会破坏已有正文内容。
检查步骤:
- 发送一个较长 AI 请求,生成中切到后台。
- 回到 App 后点击继续生成。
- 生成中关闭网络,恢复网络后再次继续生成。
通过标准:
- 切后台和断网会进入可恢复状态。
- 继续生成不会重复已应用的文本片段。
- 失败提示不暴露 token、完整服务端错误或敏感响应。
常用命令:
# 预览 APK
cd apps/mobile
eas build --platform android --profile preview
# 生产 AAB
cd apps/mobile
eas build --platform android --profile production检查项:
eas.json是否包含必要的EXPO_PUBLIC_*变量。- Clerk 是否配置移动端 redirect scheme。
- 真机权限如相册、文件上传、Haptics 是否实际验证。
pnpm start:mobile
pnpm --filter @notion/mobile lint
pnpm --filter @notion/mobile exec tsc --noEmit- 当前 Web / Mobile 差距:
web-mobile-gap-analysis.md - Mobile AI 历史排障复盘:
blog-archive.md