# @bugsplat/expo 中文文档

规范地址：https://npmcn.com/package/%40bugsplat/expo/

版本：0\.8\.2
npm 元数据更新时间：2026-10-27T01:39:59.483Z
中文译文更新时间：2026-11-08T19:27:35.827Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40bugsplat/expo
原文对照：https://npmcn.com/package/%40bugsplat/expo/?lang=original
项目主页：https://github.com/BugSplat-Git/bugsplat-expo#readme
源码仓库：https://github.com/BugSplat-Git/bugsplat-expo

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：152 kB，59 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：expo \*，react \*，expo-blob \>=55\.0\.0，react-native \*，@bugsplat/react ^2\.1\.1，expo-file-system \*，@bugsplat/symbol-upload \*
- 首次发布：2026-03-24T03:35:14.192Z
- 最新版本发布：2026-10-27T01:39:59.282Z
- 近 30 天下载量：3419（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：14（近 12 个月 14 个）

## 中文简介

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

## 安装

```sh
npm install @bugsplat/expo
```

也可以使用：`pnpm add @bugsplat/expo`、`yarn add @bugsplat/expo`、`bun add @bugsplat/expo`

## README

[![bugsplat-github-banner-basic-outline](https://user-images.githubusercontent.com/20464226/149019306-3186103c-5315-4dad-a499-4fd1df408475.png)](https://bugsplat.com/)  

# 

BugSpla

### **

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

**

[![Follow BugSplat on Bluesky](https://img.shields.io/badge/Follow%20BugSplat-Bluesky-blue?logo=bluesky&style=social)](https://bsky.app/profile/bugsplatco.bsky.social) [![Join BugSplat on Discord](https://img.shields.io/discord/664965194799251487?label=Join%20Discord&logo=Discord&style=social)](https://discord.gg/K4KjjRV5ve)  
[![@bugsplat/expo on npm](https://img.shields.io/npm/v/@bugsplat/expo?label=npm&logo=npm)](https://www.npmjs.com/package/@bugsplat/expo)

## 导言

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

## 安装

```sh
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`)或插件配置中.

```json
{
  "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: true` | BugSplate API 客户端 ID( 或设置) `BUGSPLAT_CLIENT_ID` (原始内容存档于2019-09-21) (英语). env var |
| `symbolUploadClientSecret` | 何时 `enableSymbolUpload: true` | BugSplate API 客户端秘密( 或设置) `BUGSPLAT_CLIENT_SECRET` (原始内容存档于2019-09-21) (英语). env var |

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

### 符号上传

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

用于手动上传或CI/CD工作流程,使用 [`@bugsplat/symbol-upload`](https://github.com/BugSplat-Git/symbol-upload) 直接 :

```sh
npm install --save-dev @bugsplat/symbol-upload
```

```sh
# 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` 所有选项.

## 使用量

### 初始化

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

await init('your-database', 'YourApp', '1.0.0', {
  userName: 'user@example.com',
  userEmail: 'user@example.com',
  appKey: 'optional-key',
});
```

### 报告错误

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

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

### 设置用户信息

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

setUser('Jane Doe', 'jane@example.com');
```

### 设置自定义属性

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

setAttribute('environment', 'production');
```

### 测试崩溃

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

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

### 触发原生吊( ANR)

```typescript
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上同样工作.

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

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

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

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

### 发布前收集用户输入

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

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

```tsx
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`](https://docs.expo.dev/versions/latest/sdk/sensors/)。 。 。 .

```sh
npx expo install expo-sensors
```

```tsx
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`](https://github.com/clecoffre/react-native-shake),它会听两个频道(权衡:这是一个第三方本地模块,如果忘记运行,在启动时会崩溃应用程序 `npx expo prebuild --clean` 在安装后).

### 用户反馈

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

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

```typescript
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);
```

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

```tsx
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系统** | [百叶苹果](https://github.com/BugSplat-Git/bugsplat-apple) (PLCrash Reporter) (英语) | HTTP 密码为 `/post/js/` |
| **机器人** | [百花板和机器人](https://github.com/BugSplat-Git/bugsplat-android) (崩溃) | HTTP 密码为 `/post/js/` |
| **网页** | 不详 | [错误平板js](https://github.com/BugSplat-Git/bugsplat-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()` 让你知道本地崩溃报告不活跃.

为了测试全部本地崩溃报告,请使用 **释放构建** (见 [测试原生崩溃](https://npmcn.com/package/%40bugsplat/expo/#readme-testing-native-crashes) 页:1 开发建筑包括一个调试器,在BugSplat捕捉到之前会拦截相撞.

## 测试原生崩溃

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

```sh
# 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 是什么？

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 和提交记录判断。

