mcpField
E
expo-app-clip

expo-app-clip

github.com/expo开发3.5k20.4k 次安装今天更新
代码仓库

关于 expo-app-clip

expo-app-clip 是一份指南,介绍如何为 Expo 应用添加 iOS App Clip target、配置关联域名和元数据,并构建 TestFlight 版本。适合希望在主应用旁集成 URL 启动 Clip 的 Expo 开发者。

主要功能

  1. 01创建 App Clip target
  2. 02配置关联域名和 AASA
  3. 03设置 App Store 与 Clip 元数据
  4. 04构建并提交包含 Clip 的主应用
  5. 05可选检测 App Clip 上下文

适用场景

  1. 01为 Expo 应用添加 URL 启动的 Clip
  2. 02配置 Clip 启动所需的域名关联
  3. 03准备 Expo 应用和 Clip 的 TestFlight 版本

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/expo/skills --skill expo-app-clip

安装后在 Claude Code 中输入/expo-app-clip确认已加载。

附带文件agents/openai.yamlreferences/native-module.md

详细介绍

向 Expo 应用添加 App Clip

要求。 添加 App Clip 目标是开源的。发布 App Clip 需要加入 Apple Developer Program,并通过 App Store 审核;AASA 文件必须通过 HTTPS 托管在你的域名上(任何 HTTPS 主机都可以;EAS Hosting 是一种选择)。通过 EAS Build 或 bunx testflight 构建会使用 EAS 套餐中的构建时长。请参阅 https://expo.dev/pricing 和 https://developer.apple.com/app-clips/。

向 Expo 项目添加 iOS App Clip 目标。Clip 位于 targets/clip/,与父应用一同发布,并通过 Apple App Site Association(AASA)文件,从应用域名上的 URL 启动。

父应用的 bundle ID 会变成 com.<username>.<app-name>,Clip 的 bundle ID 会自动派生为 <parent>.clip(例如 com.bacon.may20.clip)。

1. 设置 bundleIdentifier 和 appleTeamId

如果缺少这些字段,bun create target 会发出警告。在 app.json 中添加:

{
  "expo": {
    "ios": {
      "bundleIdentifier": "com.<username>.<app-name>",
      "appleTeamId": "XX57RJ5UTD"
    }
  }
}

2. 添加 App Clip 目标

bun create target clip

此命令会安装 @bacons/apple-targets,将其添加到 app.json 的 plugins 数组中,并写入以下文件:

  • targets/clip/expo-target.config.js — 目标的配置插件
  • targets/clip/Info.plist — Clip 的 Info.plist
  • targets/clip/AppDelegate.swift、Assets.xcassets 等

选择一个合适的图标,或复用应用中已定义的图标 — 在 bunx expo config 的 icon 或 ios.icon 键下查看。

3. 设置关联域名

父应用和 Clip 都需要 Associated Domains 权限,指向托管 AASA 文件的域名。

在 app.json 中添加 applinks:(父应用)和 appclips:(Clip 启动)条目:

{
  "expo": {
    "ios": {
      "associatedDomains": [
        "applinks:may20.expo.app",
        "appclips:may20.expo.app"
      ]
    }
  }
}

在 targets/clip/expo-target.config.js 中声明 Clip 的权限:

/** @type {import('@bacons/apple-targets/app.plugin').ConfigFunction} */
module.exports = (config) => ({
  type: "clip",
  icon: "https://github.com/expo.png",
  entitlements: {
    "com.apple.developer.associated-domains": ["appclips:may20.expo.app"],
  },
});

如果跳过此步骤,expo prebuild 会输出:Apple App Clip may require the associated domains entitlement but none were found。

4. 注册 bundle ID 并创建 App Store 条目

bunx setup-safari

此命令会登录 Apple Developer 账户,注册 com.bacon.may20,创建 App Store Connect 条目,并输出:

  • 入门版 apple-app-site-association JSON
  • 包含 iTunes 应用 ID 的 <meta name="apple-itunes-app"> 标签
  • Team ID、iTunes ID 和 Bundle ID

5. 托管 AASA 文件

当 iOS 获取 https://<your-domain>/.well-known/apple-app-site-association 并找到匹配的 appclips 条目时,就会启动 App Clip。

mkdir -p public/.well-known
touch public/.well-known/apple-app-site-association

粘贴 setup-safari 输出的 JSON,但要添加一个 appclips 块,其中包含 Clip 的完整应用 ID(<TeamID>.<ClipBundleID>)。setup-safari 的输出只涵盖父应用:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["XX57RJ5UTD.com.bacon.may20"],
        "components": [{ "/": "*", "comment": "Matches all routes" }]
      }
    ]
  },
  "appclips": {
    "apps": ["XX57RJ5UTD.com.bacon.may20.clip"]
  },
  "activitycontinuation": {
    "apps": ["XX57RJ5UTD.com.bacon.may20"]
  },
  "webcredentials": {
    "apps": ["XX57RJ5UTD.com.bacon.may20"]
  }
}

注意:

6. 添加 Smart App Banner meta 标签

创建 src/app/+html.tsx(Expo Router 的 HTML 外壳),并添加 setup-safari 提供的标签。如果版本化模板不存在,则创建它:

bunx expo customize src/app/+html.tsx

将 meta 标签添加到 <head>:

import { ScrollViewStyleReset } from "expo-router/html";

export default function Root({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="apple-itunes-app" content="app-id=6771566491" />
        <ScrollViewStyleReset />
      </head>
      <body>{children}</body>
    </html>
  );
}

若要让网站显示 App Clip 卡片,而不是安装卡片,请使用:

<meta
  name="apple-itunes-app"
  content="app-id=6771566491, app-clip-bundle-id=com.bacon.may20.clip, app-clip-display=card"
/>

7. 部署网站

AASA 文件必须先上线,iOS 才会信任此关联。使用 EAS Hosting:

bunx expo export -p web
eas deploy --prod

此命令会发布网站(包括 /.well-known/apple-app-site-association),地址为 https://<slug>.expo.app。验证:

curl https://may20.expo.app/.well-known/apple-app-site-association

8. 镜像权限

预构建后检查父应用的权限:

npx expo config --type introspect

查看 infoPlist 对象,将权限键镜像到 App Clip 的 Info.plist 中,以便在 Clip 中使用相应的 API。

在 Clip 的目标配置中设置 deploymentTarget: "17.6"——在 iOS 17.6 中,App Clip 的最低大小限制更高。

如果应用使用推送通知或定位服务,请在 App Clip 的 Info.plist 中添加以下内容以请求必要的权限:

<key>NSAppClip</key>
<dict>
  <key>NSAppClipRequestEphemeralUserNotification</key>
  <false/>
  <key>NSAppClipRequestLocationConfirmation</key>
  <true/>
</dict>

9. 构建并提交到 TestFlight

bunx testflight

此操作将:

  1. 如果缺少 eas.json,则生成该文件。
  2. 为两个目标(父应用 + Clip)设置凭据。每个目标都有自己的配置描述文件,但可以共用一个 Distribution Certificate。
  3. 同步功能配置——注意 Clip 目标的 Enabled: Associated Domains。
  4. 构建、上传并安排 TestFlight 提交。

10. 配置 App Clip 元数据

将现有的 App Store 元数据拉取到本地:

eas metadata:pull

将 apple.appClip 添加到 store.config.json。最多可以配置 3 个调用 URL,以便从网页启动 Clip:

{
  "configVersion": 0,
  "apple": {
    "appClip": {
      "defaultExperience": {
        "action": "PLAY",
        "releaseWithAppStoreVersion": true,
        "reviewDetail": {
          "invocationUrls": ["https://may20.expo.app/", null, null]
        },
        "info": {
          "en-US": {
            "subtitle": "Instantly native with Expo",
            "headerImage": "store/apple/app-clip/en-US/asc-app-clip.png"
          }
        }
      }
    }
  }
}

headerImage 必须是 1800x1200 的 PNG,且不含透明度。

将元数据推送回商店:

eas metadata:push

Apple 推荐的 App Clip 元数据指南:https://sosumi.ai/documentation/appclip/configuring-the-launch-experience-of-your-app-clip

最终效果

  • 父应用目标:com.bacon.may20
  • App Clip 目标:com.bacon.may20.clip,位于 targets/clip/
  • 托管于 https://may20.expo.app/.well-known/apple-app-site-association 的 AASA
  • 每个网页路由上都有 Smart App Banner meta 标签
  • 每个路由都链接到对应的原生页面
  • 内嵌 Clip 的父应用 TestFlight 构建版本

Apple 从域名中的 URL 启动 Clip 后,iOS 会打开 targets/clip/ 的入口点并加载 React Native 应用。

原生检测(可选)

若要让 JS 检测当前是否在 App Clip 中运行,并显示完整应用的安装提示,请创建本地 Expo 模块(bunx create-expo-module --local),以公开 navigator.appClip.prompt()。

Swift 模块、TypeScript 接口和用法请参阅 ./references/native-module.md。

参考资料

  • ./references/native-module.md — 用于检测 App Clip 上下文并显示 SKOverlay 安装提示的本地 Expo 模块

提交反馈

如果你在此技能中遇到错误、误导性信息或过时信息,请提交报告,以便 Expo 改进:

npx --yes @expo/agent-cli@latest feedback --category skills --subject "expo-app-clip" "<actionable feedback>"

仅在有具体且可执行的反馈时提交。请尽可能提供相关背景信息。 如果 Agent 多次无法完成 Expo 任务,或用户不得不介入,请简要报告任务、预期结果和问题所在,并使用 --category evals,同时将相关 Expo 包或命令作为 --subject。

评论

支持 Markdown