SuperAPI AI 工具集

deep-links-and-universal-links

编程与开发

查看项目

更新于 10-18 18:03

技能介绍

用途

本技能用于在 React Native(Expo Router)应用中安全地接入和管理深链与通用链接。它把每一个打开应用的链接——自定义 scheme、iOS 通用链接(universal link)、Android App Link,无论冷启动还是热启动——都汇聚到同一个同步网关处理,只允许打开白名单内的路由,并对链接参数做校验。

主要能力

  • 单一网关:src/app/+native-intent.tsx 导出 redirectSystemPath,把所有 URL(冷启动 initial: true、热启动 initial: false)交给 routeIncomingLink 处理,只返回其决定。其他代码不得再订阅链接(不使用 'url' 监听、getInitialURL、getLinkingURL、useLinkingURL、useURL 或 legacy_subscribe)。
  • 同步且完备的判定:判定在 attempt(...) 内运行,崩溃会上报错误网并视为拒绝;判定中不使用 async、await、then 或 fetch。短链和推荐码在落地路由中解析并自我替换。
  • 路由白名单:LINK_ROUTES 按 URL 路径列出每个可链接路由(去掉分组、不用 catch-all),每项都对应真实路由文件;其他链接一律打开首屏。
  • 参数校验:每个动态段有类型(slug、uuid、int);未知查询键(如 utm_source、fbclid)被丢弃;重复保留键、控制字符或超过 256 字符的值被拒绝;查询键不得遮蔽段名;网关返回编码后的路径。屏幕仍用自己的 valibot 解析器解析参数。
  • 冷热行为区分:被拒绝的冷链接落到首屏;被拒绝的热链接不做任何改变(冷返回 /,热返回 null),被拒绝的 URL 不显示。
  • 受保护路由的待处理链接:进入受保护分组的链接会等待,登录后只打开一次;入口声明 gate 并在 open() 中构建类型化 href,守卫方调用 useLinkGate(gate, isOpen),守卫后首屏调用 useOpenPendingLink(gate)。
  • 密钥链接:携带 token、密码、OTP、magic 或 reset code 的路由标记为 verifiedOnly(仅限已验证主机的 http(s));密钥一次性、短时效并在屏幕上确认。
  • 链接只打开屏幕,不执行动作、不转发:链接打开的路由不在到达时变更、购买、删除、登录或改设置;链接参数不进入 Linking.openURL 或浏览器,也不成为 href。
  • 生产环境拒绝调试路由:调试链接入口标记 testBuildOnly: true。
  • 已验证主机契约:contracts/deep-links.json 按变体列出主机;linkNativeConfig() 生成 applinks:<host> 条目和一个 App Links 过滤器;网关只接受当前运行配置的主机。
  • 托管文件生成:每个主机的 AASA 和 assetlinks.json 由 write-well-known.mjs 生成,需人工部署到 https://<host>/.well-known/(HTTPS、无重定向)。
  • 发布前检查:assetlinks 指纹须是签名实际安装包的密钥(Play App Signing 的,而非上传密钥);--release 会在 example.com 主机、com.example.* id 和未填 token 上失败。
  • 测试:每个链接路由都做冷、热测试,通过真实路由器的 Jest 测试,再用命名设备或 Maestro openLink 验证。

使用方式

  1. 阅读任务所需参考:首次设置/新链接屏幕/参数/网关/冷热/通知或 OAuth 链接读 references/link-routing.md;通用链接、App Links、AASA、assetlinks.json、指纹、托管读 references/universal-and-app-links.md;在模拟器或 Maestro 中试链接读 references/device-testing.md;FAIL 行、回放、配置读 references/checker.md;React Navigation 应用读 references/react-navigation-linking.md。
  2. 一次性搭建网关:复制 templates/src/app/+native-intent.tsx、templates/src/core/links/、templates/src/features/deep-links/、templates/src/services/deep-links/、templates/src/hooks/ 中的两个 hook 以及 templates/contracts/(每个测试随文件)。运行 npx jest src/core/links src/features/deep-links src/services/deep-links src/hooks --selectProjects unit。
  3. 链接一个屏幕:在 examples/link-routes-tasks.ts 之后把入口加入 LINK_ROUTES(URL 路径、每段类型、屏幕读取的查询键、密钥用 verifiedOnly);受守卫的加 gate 和 open,并在守卫处调用 useLinkGate、首屏模型调用 useOpenPendingLink;为新路由在 deep-links-navigation.test.tsx 加冷热用例。
  4. 添加已验证链接(应用有域名时):填写 contracts/deep-links.json,按 examples/app-config-deep-links.ts 把 templates/scripts/deep-links/link-native-config.ts 接入 app.config.ts,做新的原生构建,交给 expo-prebuild-and-config-plugins 刷新原生快照并提交;然后运行 node ${CLAUDE_SKILL_DIR}/scripts/write-well-known.mjs .,并请开发者部署各 <wellKnownDir>/<host>/ 文件夹并确认指纹。
  5. 在设备上试(references/device-testing.md):在命名模拟器和模拟器上做冷热测试,Android 用 pm get-app-links 验证;把流程交给 e2e-maestro。
  6. 运行检查:node ${CLAUDE_SKILL_DIR}/scripts/check-deep-links.mjs .,修复每个 FAIL 行并重跑至 RESULT: PASS;CI 中另跑 node ${CLAUDE_SKILL_DIR}/scripts/write-well-known.mjs . --check;发布前用 --release 运行检查器。

适用场景

  • 为 React Native / Expo Router 应用添加深链、scheme、关联域。
  • 需要统一管控所有进入链接、防止任意页面或二维码打开敏感路由(账户删除、结账、调试屏)。
  • 需要处理冷启动与热启动链接、受保护路由登录后跳转、OAuth 与通知链接。
  • 需要生成并校验 AASA 与 assetlinks.json、管理已验证主机与指纹。
  • 需要在设备与 Maestro 中测试链接流程。

限制

  • 该技能在 2026-10-14 用 Expo SDK 57(expo 57.0.26)、expo-router 57.0.24、expo-linking 57.0.11 在 Jest 中于真实路由器内并用 npx expo config 验证,尚未在设备上驱动。
  • 托管文件需人工部署到 HTTPS 且无重定向;iOS 在安装时及之后约每周通过 Apple CDN 获取 AASA,Android 在安装时验证,文件错误会静默失败。
  • 自定义 scheme 任何应用都可注册接收,密钥只能走已验证链接。
  • 其他具体收费、价格、平台支持范围等事实暂未提供。

反模式(须避免)

  • +native-intent 返回“暂时”路径;应只返回 routeIncomingLink 的决定。
  • 在屏幕中使用 Linking.addEventListener('url') 或 useLinkingURL(),会双重处理并跳过网关。
  • 在 redirectSystemPath 中用 await fetch 解析短链,会让启动等待网络。
  • 对打开无内容的链接用 router.navigate('/'),会丢弃工作;应返回 null。
  • 在自定义 scheme 上放密码重置或 magic-link token。
  • 链接到达即完成、加入、支付或删除。
  • Linking.openURL(params.url),构成开放重定向。
  • 因未知查询键拒绝链接;应丢弃 utm_* 和 fbclid。
  • applinks:https://example.com 或没有 autoVerify 的 https 过滤器。
  • 用上传密钥指纹配 Play App Signing。
  • 手工编辑托管的 AASA。
  • 分享 tasks://... 链接。
  • 多个模拟器运行时用 npx uri-scheme open 或 simctl openurl booted;应指定设备。