@bugsplat/expo

中文文档
0.8.2发布于 2026/10/27MITTypeScriptCommonJS零依赖近 30 天下载 3419

BugSplate 崩溃和错误报告 Expo 应用程序横跨 iOS、 Android 和 Web

中文使用文档
文档目录35 节
  1. 为繁忙的开发者构建了崩溃和错误报告 .
  2. 导言
  3. 安装
  4. 配置
  5. 插件选项
  6. 符号上传
  7. 使用量
  8. 初始化
  9. 报告错误
  10. 设置用户信息
  11. 设置自定义属性
  12. 测试崩溃
  13. 触发原生吊( ANR)
  14. 错误边界
  15. 发布前收集用户输入
  16. 摇摆以发送反馈
  17. 用户反馈
  18. 如何运作
  19. API 密码
  20. init(database, application, version, options?)
  21. post(error, options?)
  22. postFeedback(title, options?)
  23. useFeedback()
  24. ErrorBoundary
  25. setUser(name, email)
  26. setAttribute(key, value)
  27. crash()
  28. hang()
  29. 博览去
  30. 测试原生崩溃
  31. 测试本地挂接( ANRs)
  32. 解决问题
  33. Android: 没有上传到模拟器上的崩溃
  34. iOS: 测试崩溃后没有崩溃报告
  35. 许可证

bugsplat-github-banner-basic-outline

BugSpla

为繁忙的开发者构建了崩溃和错误报告 .

Follow BugSplat on Bluesky Join BugSplat on Discord
@bugsplat/expo on npm

导言

BugSplate 的标签 @bugsplat/expo 软件包为跨越iOS、Android和Web的Expo应用程序提供崩溃和错误报告。 BugSplact为您提供了宝贵的洞察力,帮助您了解用户遇到的问题。 我们的"博览会"集成收集了本土崩溃报告,JavaScript出错,以及自定义元数据,以便您能够修复错误并提供更好的用户体验.

安装

npx expo install @bugsplat/expo expo-blob expo-file-system @bugsplat/react

expo-blob, (中文(简体) ), expo-file-system 财务报告和审定财务报表 @bugsplat/react 是同行的依赖性,所以每个拷贝都最终会出现在您的应用程序中. 支持SDK 55至58.

expo-blob 船舶本地代码必须匹配您的项目 Expo SDK, 所以安装您的 SDK 的放行.. 58.x 为SDK 58, 57.x 用于SDK 57等(例如: npm install expo-blob@~58.0.3) (中文(简体) ). 它尚未列入博览会捆绑的本地模块清单,所以 expo install 不会为您定下责任.

配置

将配置插件添加到您的 app.json 或者说 app.config.js数字 :

符号上传的证书可以通过环境变量设置(BUGSPLAT_CLIENT_ID, (中文(简体) ), BUGSPLAT_CLIENT_SECRET)或插件配置中.

{
  "expo": {
    "plugins": [
      ["@bugsplat/expo", {
        "database": "<your-database>",
        "enableSymbolUpload": true
      }],
      ["expo-build-properties", {
        "android": {
          "minSdkVersion": 26
        }
      }]
    ]
  }
}

替换 <your-database> 使用您真正的 BugSplate 数据库名称 。 插件拒绝角括号占位符 expo prebuild 所以这个准确的片段不会意外地作为配置船出航.

这个 bugsplat-android SDK需要Android minSdk 26 (Android 8.0+). 如果你的项目的minSdk 已经 \ 26 expo-build-properties 不需要插件 .

插件设置了所需的本地权限(Android),可选配置两个平台的自动符号上传. 通过代码配置您的数据库 init()。 。 。 .

插件选项

选项需求说明
database对BugSplate 数据库名称 。 掷出 expo prebuild 如果缺少, 空的, 或设置到一个占位符, 如 "<your-database>"成为真相的来源——也为运行时间所用 init() 调用从应用程序代码读取.
enableSymbolUpload没有启用iOS(dSYMs + JS源地图)和Android(.so文件 + Hermes JS源地图)的自动符号上传.
symbolUploadClientId何时 enableSymbolUpload: trueBugSplate API 客户端 ID( 或设置) BUGSPLAT_CLIENT_ID (原始内容存档于2019-09-21) (英语). env var
symbolUploadClientSecret何时 enableSymbolUpload: trueBugSplate API 客户端秘密( 或设置) BUGSPLAT_CLIENT_SECRET (原始内容存档于2019-09-21) (英语). env var

插件也验证 expo.name, (中文(简体) ), expo.version,以及 expo.android.package 在预建时 —— 这些流入到符号加载脚本中, 因此上传的身份匹配您崩溃时的应用程序报告 .

符号上传

生产崩溃报告需要调试符号才能产生可读的堆栈痕迹. 何时 enableSymbolUpload 设置中,配置插件在iOS和Android发行过程中自动上传符号.

用于手动上传或CI/CD工作流程,使用 @bugsplat/symbol-upload 直接 :

npm install --save-dev @bugsplat/symbol-upload
# Upload iOS dSYMs
npx @bugsplat/symbol-upload \
  -b your-database -a YourApp -v 1.0.0 \
  -i $BUGSPLAT_CLIENT_ID -s $BUGSPLAT_CLIENT_SECRET \
  -d /path/to/build/Products/Release-iphoneos \
  -f "**/*.dSYM"

# Upload Android .so files (converted to .sym)
npx @bugsplat/symbol-upload \
  -b your-database -a YourApp -v 1.0.0 \
  -i $BUGSPLAT_CLIENT_ID -s $BUGSPLAT_CLIENT_SECRET \
  -d android/app/build/intermediates/merged_native_libs \
  -f "**/*.so" -m

# Upload JavaScript source maps (after npx expo export --source-maps)
npx @bugsplat/symbol-upload \
  -b your-database -a YourApp -v 1.0.0 \
  -i $BUGSPLAT_CLIENT_ID -s $BUGSPLAT_CLIENT_SECRET \
  -d dist \
  -f "**/*.map"

运行 npx @bugsplat/symbol-upload --help 所有选项.

使用量

初始化

import { init } from '@bugsplat/expo';

await init('your-database', 'YourApp', '1.0.0', {
  userName: '[email protected]',
  userEmail: '[email protected]',
  appKey: 'optional-key',
});

报告错误

import { post } from '@bugsplat/expo';

try {
  riskyOperation();
} catch (error) {
  const result = await post(error);
  console.log(result.success ? 'Reported!' : result.error);
}

设置用户信息

import { setUser } from '@bugsplat/expo';

setUser('Jane Doe', '[email protected]');

设置自定义属性

import { setAttribute } from '@bugsplat/expo';

setAttribute('environment', 'production');

测试崩溃

import { crash } from '@bugsplat/expo';

// Triggers a native crash (iOS/Android) or throws an error (web)
crash();

触发原生吊( ANR)

import { hang } from '@bugsplat/expo';

// Freezes the UI thread in a native loop. On Android the system ANR detector
// fires after ~5s of unresponsive input and BugSplat captures a dump with
// symbolicated native frames. On iOS the bundled BugSplat-Apple hang tracker
// persists a fatal-hang report after the main thread stays unresponsive past
// its threshold (~2s by default); the report uploads on the next app launch.
hang();

错误边界

将组件树包入 <ErrorBoundary> 以捕获 React 生成错误并自动报告到 BugSplate 。 在iOS,Android,和Web上同样工作.

import { ErrorBoundary } from '@bugsplat/expo';

function App() {
  return (
    <ErrorBoundary fallback={<Text>Something went wrong</Text>}>
      <MyComponent />
    </ErrorBoundary>
  );
}

倒置道具接受反应节点或渲染函数:

<ErrorBoundary
  fallback={({ error, resetErrorBoundary }) => (
    <View>
      <Text>{error.message}</Text>
      <Button title="Try again" onPress={resetErrorBoundary} />
    </View>
  )}
>
  <MyComponent />
</ErrorBoundary>

发布前收集用户输入

默认, <ErrorBoundary> 当错误发生时, 便张贴到 BugSplat 。 如果你宁可给用户一个机会来描述他们首先正在做的事情——将它捆绑在一份报告中而不是两份报告中——设定 disablePost 在边界上,并手动从后退位置张贴:

<ErrorBoundary> 是类成分,所以钩子不能直接活在它内部 fallback 使道具——将回落到自己的功能组件中:

import { useRef, useState } from 'react';
import { ErrorBoundary, post, type FallbackProps } from '@bugsplat/expo';
import { Text, TextInput, Button, View } from 'react-native';

function ErrorFallback({ error, componentStack, resetErrorBoundary }: FallbackProps) {
  const [description, setDescription] = useState('');
  const posted = useRef(false);

  const submit = async () => {
    if (posted.current) return;
    posted.current = true;
    await post(error, {
      description,
      attributes: { route: 'tasks/123' },
      attachments: componentStack
        ? [{
            filename: 'componentStack.txt',
            data: new Blob([componentStack], { type: 'text/plain' }),
          }]
        : undefined,
    });
  };

  return (
    <View>
      <Text>Something went wrong: {error.message}</Text>
      <TextInput value={description} onChangeText={setDescription} />
      <Button title="Submit" onPress={submit} />
      <Button title="Dismiss" onPress={() => { submit(); resetErrorBoundary(); }} />
    </View>
  );
}

<ErrorBoundary disablePost fallback={(props) => <ErrorFallback {...props} />}>
  <App />
</ErrorBoundary>

关于这种模式的一些说明:

  • post() 实值 没有 一相能发. 这个 useRef 警卫是消费者的责任——没有它,一个快的双塔普(或"投降后解散")会发射出两个报告. useRef 同步更新,它会保护同一窗口的地盘; useState 不会的.
  • componentStack 被包裹在一个 Blob在本地,附着物也可以是一种 Uint8Array 或一个 { uri, type } 文件引用( 如 a) expo-image-picker 资产; @bugsplat/expo 从磁盘中读取文件引用 expo-file-system 当报告发布时.
  • attributes 成为BugSplate仪表板中的可查询列——用于按路由,特征旗,构建通道等过滤崩溃.
  • 如果发布失败, 您需要重试, 请检查 success 返回值的属性 post() 并重设 posted.current 相应. 食谱上并没有显示它能保持最小.

摇摆以发送反馈

常见模式:让用户摇动设备打开反馈对话框. @bugsplat/expo 不捆绑摇动探测器(以保持软件包的收缩),但接线需要~30行 expo-sensors。 。 。 .

npx expo install expo-sensors
import { useEffect, useRef, useState } from 'react';
import { Accelerometer } from 'expo-sensors';
import { postFeedback } from '@bugsplat/expo';

function useShake(onShake: () => void, enabled = true) {
  const lastFire = useRef(0);
  const cb = useRef(onShake);
  cb.current = onShake;
  useEffect(() => {
    if (!enabled) return;
    Accelerometer.setUpdateInterval(100);
    const sub = Accelerometer.addListener(({ x, y, z }) => {
      // values are in g-units; magnitude ≈ 1 at rest (gravity)
      if (Math.abs(Math.sqrt(x * x + y * y + z * z) - 1) < 1.2) return;
      const now = Date.now();
      if (now - lastFire.current < 1500) return; // 1.5s cooldown
      lastFire.current = now;
      cb.current();
    });
    return () => sub.remove();
  }, [enabled]);
}

function App() {
  const [open, setOpen] = useState(false);
  // Auto-disabled while the modal is open so the user's input shake
  // can't bounce them right back into it.
  useShake(() => setOpen(true), !open);
  return /* ... feedback modal that calls postFeedback() on submit ... */;
}

测试:真正的iOS/Android设备在框外工作. Android模拟器可以通过扩展控制 →虚拟传感器来模拟摇晃. iOS 模拟器 Device → Shake 菜单 没有 火速计数据——它发送 UIEventSubtypeMotionShake一个不同的频道。 如果iOS 模拟测试对您很重要, 请互换 expo-sensors 页:1 react-native-shake,它会听两个频道(权衡:这是一个第三方本地模块,如果忘记运行,在启动时会崩溃应用程序 npx expo prebuild --clean 在安装后).

用户反馈

提交用户反馈到您的 BugSplate 数据库 。 在iOS,Android,和Web上工作.

紧急API——以后的任何地方的电话 init()数字 :

import { postFeedback } from '@bugsplat/expo';

const result = await postFeedback('Login button broken', {
  description: 'Nothing happens when I tap sign in',
});
console.log(result.success ? `Feedback #${result.crashId} posted` : result.error);

反应钩子——用于驱动带有内置加载/误入状态的反馈表:

import { useFeedback } from '@bugsplat/expo';

function FeedbackForm() {
  const { postFeedback, loading, error } = useFeedback();

  return (
    <Button
      title={loading ? 'Sending…' : 'Send feedback'}
      disabled={loading}
      onPress={() =>
        postFeedback('Login button broken', {
          description: 'Nothing happens when I tap sign in',
        })
      }
    />
  );
}

如何运作

平台原生崩溃JS 错误报告
iOS系统百叶苹果 (PLCrash Reporter) (英语)HTTP 密码为 /post/js/
机器人百花板和机器人 (崩溃)HTTP 密码为 /post/js/
网页不详错误平板js

API 密码

init(database, application, version, options?)

初始化 BugSplate 崩溃报告 。 必须在其他功能之前调用 .

选项 :

  • appKey?: string - 可查询元数据密钥
  • userName?: string - 报告的用户名
  • userEmail?: string - 报告用户电子邮件
  • autoSubmitCrashReport?: boolean - 自动提交崩溃(仅iOS,默认:真实)
  • attributes?: Record<string, string> - 自定义密钥值属性
  • attachments?: string[] - 要附加的文件路径( 仅本地)
  • description?: string - 默认描述

post(error, options?)

手动报告出错 。 回返 { success: boolean, error?: string }。 。 。 .

postFeedback(title, options?)

提交用户反馈. title 简称(需要); options.description 持有更长的身体。 回返 { success: boolean, error?: string, crashId?: number }。 。 。 .

useFeedback()

反应钩子返回 { postFeedback, loading, response, error } 用于驱动反馈表.

ErrorBoundary

反应错误边界, 报告会自动向 BugSplate 提交错误 。 接受一个 fallback (反应节点或使函数接收) { error, componentStack, response, resetErrorBoundary }) (中文(简体) ).

setUser(name, email)

为以后的报告更新用户信息.

setAttribute(key, value)

设置自定义属性 。 注:不支持网上.

crash()

触发测试崩溃以验证整合 .

hang()

冻结本地循环中的 UI 线程 。 在Android上,这会产生一个真实的ANR,带有符号化的原生帧;在iOS上,BugSplate-Apple悬浮跟踪器在无响应阈值(~2s)后坚持了致命悬浮报告,并上传到下一次发射时. 需要开发建设——在博览会Go中不开放.

博览去

@bugsplat/expo 在博览会Go中工作,功能减少。 由于博览会Go没有本地模块,本地崩溃报告被禁用. JS 错误报告(init(), (中文(简体) ), post(), (中文(简体) ), postFeedback(), (中文(简体) ), setUser(), (中文(简体) ), setAttribute(), (中文(简体) ), ErrorBoundary)仍然通过HTTP倒计时操作. 警告已经登录 init() 让你知道本地崩溃报告不活跃.

为了测试全部本地崩溃报告,请使用 释放构建 (见 测试原生崩溃 页:1 开发建筑包括一个调试器,在BugSplat捕捉到之前会拦截相撞.

测试原生崩溃

要测试本地崩溃报告, 您必须运行一个 释放构建 ——调试器在调试中拦截相撞事件建立.

# iOS
npx expo run:ios --configuration Release

# Android
npx expo run:android --variant release

iOS系统: 崩溃报告被PLCrash Reporter和 上传到下一个应用程序发布 何时 init() 又被调用。 启动测试后,重新启动应用程序并呼叫 init() 上传待处理的报告.

机器人: 抓获崩溃报告 崩溃时立即上传 由 Crashpad 处理程序.

测试本地挂接( ANRs)

hang() 在一个本地环路中封锁主线程。 每个平台的处理略有不同:

  • 机器人:系统ANR探测器在~5秒的无响应输入后起火,BugSplatz立即用符号化的本土帧来捕获垃圾.
  • iOS系统:被捆绑的 BugSplat-Apple 悬浮跟踪器在主线被挡在阈值(~2s)后,坚持了致命的悬浮报告. 报告在下个应用程序发布会上传.

触发和核实:

  1. 打电话 hang() (例如从调试按钮).
  2. 机器人:将屏幕敲了几下——系统"App Not response"对话框出现,垃圾被捕获.
  3. iOS系统: 一旦UI冻结(或等待OS监视器),应用程序切换器的强制-quit.
  4. 重启应用程序. 悬浮报告在下一次发射时上传到任何未决的坠机报告.

解决问题

Android: 没有上传到模拟器上的崩溃

Crashpad 处理程序要求本地库被取入磁盘. 这个 @bugsplat/expo 配置插件通过设置自动打开遗留的 JNI 容器 expo.useLegacyPackaging=true 内 android/gradle.properties (设置与 expo-build-properties' android.useLegacyPackaging,所以不要设置一个到 false) (中文(简体) ). 它没有设置 android:extractNativeLibs 在清单中,因为 Expo SDK 58 使用的Android Gradle插件失败了其中的构建。 如果你还没有看到坠机:

  • 使用一个 google_apis 模拟图像( 不) google_apis_playstore) (中文(简体) ). Play Store模拟器的图像有限制,阻止了Crashpad的处理程序执行.
  • 或者,在 物理和机器人设备 如果这不是一个问题.

iOS: 测试崩溃后没有崩溃报告

确保你 重新启动应用程序并呼叫 init() 再来一次 坠机后 PLCrash Reporter将崩溃保存到磁盘上,并在下一次发布时上传.

许可证

麻省理工学院

版本与发布记录

@bugsplat/expo 共发布 14 个版本,首次发布于 2026/03/24;过去 12 个月发布了 14 个版本。

版本发布日期距今
0.8.2latest2026/10/2712 天前
0.8.12026/10/1623 天前
0.8.02026/10/1623 天前
0.7.02026/05/195 个月前
0.6.02026/04/196 个月前
0.5.12026/04/186 个月前

关于 @bugsplat/expo 的常见问题

@bugsplat/expo 是什么?

BugSplate 崩溃和错误报告 Expo 应用程序横跨 iOS、 Android 和 Web

如何安装 @bugsplat/expo?

在项目目录运行 npm install @bugsplat/expo,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:expo(*)、react(*)、expo-blob(>=55.0.0)、react-native(*)、@bugsplat/react(^2.1.1)、expo-file-system(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bugsplat/expo 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bugsplat/expo 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@bugsplat/expo 可以商用吗?

@bugsplat/expo 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bugsplat/expo 的下载量有多少?

根据 npm 官方下载统计,@bugsplat/expo 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,419 次,日均约 114 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bugsplat/expo 还在维护吗?

最新版本 0.8.2 发布于 2026/10/27(12 天前);至今共发布 14 个版本,其中过去 12 个月发布了 14 个;首次发布于 2026/03/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。