# Metro

## Learn about the Metro bundler and how to configure it for your application with Sentry React Native SDK.

Sentry's React Native SDK package ships with a Sentry Metro Plugin which allows you to automatically generate Debug IDs for your applications' bundles. This is crucial for making source maps work properly with Sentry. The plugin also helps you to annotate React component names so they are available in breadcrumbs and minimize the bundle size by removing unused SDK features. This page will guide you through the process of setting up the Metro Plugin for your application.

## [Prerequisities](#prerequisities)

* [Sign up for an account](https://sentry.io/signup/)
* [Install Sentry React Native SDK](/platforms/react-native/) version 5.17.0 or newer
  * Expo is supported from SDK version 5.16.0-alpha.1

## [Configuration](#configuration)

The Sentry React Native SDK allows multiple ways to configure the Sentry Metro Plugin, depending on your current use of the Metro configuration.

### [Use the Sentry Metro Plugin](#use-the-sentry-metro-plugin)

The example below shows how to use the Sentry Metro Plugin with the default config.

`metro.config.js`

```javascript
const { getDefaultConfig } = require("@react-native/metro-config");
const { withSentryConfig } = require("@sentry/react-native/metro");

const config = getDefaultConfig(__dirname);
module.exports = withSentryConfig(config);
```

### [Add a Custom Babel Transformer](#add-a-custom-babel-transformer)

If you already have a custom transformer, ensure that the Sentry Metro Plugin is applied as the last step. The Sentry Metro Plugin doesn't overwrite the existing configuration, it extends or wraps existing properties.

`metro.config.js`

```javascript
const { getDefaultConfig } = require("@react-native/metro-config");
const { withSentryConfig } = require("@sentry/react-native/metro");

const config = getDefaultConfig(__dirname);

config.transformer = {
  ...config.transformer,
  babelTransformerPath: require.resolve("react-native-custom-transformer"),
};

module.exports = withSentryConfig(config);
```

### [Wrap Your Custom Serializer](#wrap-your-custom-serializer)

If you already have a custom serializer, you can wrap it with the Sentry Metro Serializer and call `options.sentryBundleCallback` before serializing the bundle content.

`metro.config.js`

```javascript
const {
  getDefaultConfig,
  mergeConfig,
} = require("@react-native/metro-config");
const { withSentryConfig } = require("@sentry/react-native/metro");

const myCustomSerializer = (entryPoint, preModules, graph, options) => {
  let bundle = prepareBundle(entryPoint, preModules, graph, options);
  if (options.sentryBundleCallback) {
    // Callback adds Sentry Debug IDs module to the bundle
    bundle = options.sentryBundleCallback(bundle);
  }
  const code = createCode(bundle);
  const map = createSourceMap();
  return { code, map };
};

const config = {
  serializer: {
    customSerializer: myCustomSerializer,
  },
};

module.exports = withSentryConfig(
  mergeConfig(getDefaultConfig(__dirname), config),
);
```

Expected bundle intermediate structure:

```typescript
export type Bundle = {
  modules: Array<[id: number, code: string]>;
  post: string;
  pre: string;
};
```

## [Troubleshooting](#troubleshooting)

* Sentry Metro Serializer can't add Debug ID to the Hermes Composed Source Maps. Please see [Manual Upload With Hermes](/platforms/react-native/sourcemaps/#manual-upload-with-hermes) guide on how to add Debug ID to the Hermes Composed Source Maps.
* If you see `Debug ID was not found in the bundle.` error message the `sentryBundleCallback` was not called by your custom serializer.
* If Metro configuration is missing in your Expo project, create it using `npx expo customize metro.config.js`. Read more about [Customizing Expo Metro Configuration](https://docs.expo.dev/guides/customizing-metro/).
