Expo
For Expo projects, wrap Expo's own Metro serializer with createSerializer.
Using an AI coding agent? Point it at the setup-react-native-bundle-discovery skill to install react-native-bundle-discovery automatically.
- Install the package:
yarn add -D react-native-bundle-discovery- Wrap the serializer in
metro.config.js(runnpx expo customize metro.config.jsif you don't have one yet):
const { getDefaultConfig } = require('expo/metro-config');
+const { createSerializer } = require('react-native-bundle-discovery');
const config = getDefaultConfig(__dirname);
+if (process.env.BUNDLE_ANALYZER) {
+ config.serializer.customSerializer = createSerializer({
+ projectRoot: __dirname, // ⚠️ In a monorepo, use the monorepo root instead
+ serializer: config.serializer.customSerializer, // keep Expo's serializer
+ // `expo export:embed` force-exits before the background npm metadata fetch
+ // finishes, so the report would never be written
+ fetchPackagesMetadata: false,
+ });
+}
module.exports = config;Why `fetchPackagesMetadata: false`?
expo export:embed force-exits the process right after the bundle is written.
The npm registry metadata (publish date, deprecation, latest version) is fetched in the background, so the report would never be saved.
Without it, the deprecated and outdated package recommendations are not available.
See all options in createSerializer.
- Build a release bundle with the
BUNDLE_ANALYZERenvironment variable:
BUNDLE_ANALYZER=1 npx expo export:embed \
--platform ios \
--dev false \
--entry-file node_modules/expo-router/entry.js \
--bundle-output build/ios/main.jsbundle \
--assets-dest build/iosNot using Expo Router? Point --entry-file at your app entry (the main field of package.json, e.g. index.js).
- After the build,
metro-stats.jsonis in the root of your project. Analyze it:
npx react-native-bundle-discovery-ui metro-stats.json # UI
npx react-native-bundle-discovery-cli metro-stats.json # CLI