Skip to main content
The bundle command builds a JavaScript bundle from your React Native app’s source code, which can be used for production builds or offline distribution.

Usage

npx react-native bundle --entry-file <path> [options]

Options

OptionDescriptionDefault
--entry-file <path>Path to the root JS fileRequired
--platform <string>Target platform: ios or androidios
--dev [boolean]Development mode (disables optimization)true
--minify [boolean]Minify the bundleOpposite of --dev
--bundle-output <string>Output path for the bundle fileRequired
--bundle-encoding <string>Bundle encoding (utf8, utf16le, ascii)utf8
--sourcemap-output <string>Output path for source mapNone
--sourcemap-sources-root <string>Root path for source map sourcesNone
--sourcemap-use-absolute-pathUse absolute paths in source mapfalse
--assets-dest <string>Directory for bundled assetsNone
--asset-catalog-dest <string>Path for iOS Asset CatalogNone
--reset-cacheClear Metro bundler cachefalse
--read-global-cacheRead from global cachefalse
--config <string>Path to Metro config filemetro.config.js
--max-workers <number>Maximum worker processesCPU cores
--transformer <string>Custom transformer pathDefault
--unstable-transform-profile <string>JS engine profile (hermes, default)default
--resolver-option <string...>Custom resolver options (key=value)None

Examples

Basic iOS Bundle

npx react-native bundle \
  --entry-file index.js \
  --platform ios \
  --dev false \
  --bundle-output ios/main.jsbundle \
  --assets-dest ios

Basic Android Bundle

npx react-native bundle \
  --entry-file index.js \
  --platform android \
  --dev false \
  --bundle-output android/app/src/main/assets/index.android.bundle \
  --assets-dest android/app/src/main/res

Production Bundle with Source Maps

npx react-native bundle \
  --entry-file index.js \
  --platform ios \
  --dev false \
  --minify true \
  --bundle-output ./build/main.jsbundle \
  --sourcemap-output ./build/main.jsbundle.map \
  --assets-dest ./build

Bundle for Hermes

npx react-native bundle \
  --entry-file index.js \
  --platform android \
  --dev false \
  --bundle-output android/app/src/main/assets/index.android.bundle \
  --assets-dest android/app/src/main/res \
  --unstable-transform-profile hermes

Development Bundle

npx react-native bundle \
  --entry-file index.js \
  --platform ios \
  --dev true \
  --bundle-output ./dev.bundle \
  --sourcemap-output ./dev.bundle.map

Reset Cache

npx react-native bundle \
  --entry-file index.js \
  --platform android \
  --bundle-output ./output.bundle \
  --reset-cache

Platform-Specific Bundling

iOS

npx react-native bundle \
  --entry-file index.js \
  --platform ios \
  --dev false \
  --bundle-output ios/main.jsbundle \
  --assets-dest ios
Output:
  • ios/main.jsbundle - JavaScript bundle
  • ios/assets/ - Images and other assets

Android

mkdir -p android/app/src/main/assets

npx react-native bundle \
  --entry-file index.js \
  --platform android \
  --dev false \
  --bundle-output android/app/src/main/assets/index.android.bundle \
  --assets-dest android/app/src/main/res
Output:
  • android/app/src/main/assets/index.android.bundle - JavaScript bundle
  • android/app/src/main/res/drawable-* - Images
  • android/app/src/main/res/raw/ - Other assets

Hermes Bytecode

For better performance on Android, compile to Hermes bytecode:

Step 1: Create Bundle

npx react-native bundle \
  --platform android \
  --dev false \
  --entry-file index.js \
  --bundle-output index.android.bundle \
  --assets-dest android/app/src/main/res \
  --unstable-transform-profile hermes

Step 2: Compile to Bytecode

# Path to hermesc (adjust based on your installation)
HERMESC="./node_modules/react-native/sdks/hermesc/osx-bin/hermesc"

$HERMESC \
  -O \
  -emit-binary \
  -out index.android.bundle.hbc \
  index.android.bundle

# Replace original bundle
mv index.android.bundle.hbc android/app/src/main/assets/index.android.bundle
Modern React Native Android builds handle Hermes compilation automatically during the Gradle build process.

Source Maps

Source maps enable debugging of production bundles.

Generate Source Map

npx react-native bundle \
  --entry-file index.js \
  --platform ios \
  --dev false \
  --bundle-output main.jsbundle \
  --sourcemap-output main.jsbundle.map

Upload to Error Tracking

For services like Sentry:
sentry-cli releases files VERSION upload-sourcemaps \
  --dist BUILD_NUMBER \
  --rewrite main.jsbundle.map

Debug with Source Map

# Install source-map
npm install -g source-map

# Look up original position
node -e "const sm = require('source-map'); \
const fs = require('fs'); \
const map = JSON.parse(fs.readFileSync('main.jsbundle.map')); \
const consumer = new sm.SourceMapConsumer(map); \
console.log(consumer.originalPositionFor({line: 123, column: 45}));"

Asset Handling

Image Assets

Images are automatically resolved and bundled:
// In your code
<Image source={require('./assets/logo.png')} />
After bundling, images are placed in:
  • iOS: assets/ directory
  • Android: res/drawable-* directories (organized by DPI)

iOS Asset Catalog

Generate an Asset Catalog for iOS:
npx react-native bundle \
  --entry-file index.js \
  --platform ios \
  --dev false \
  --bundle-output main.jsbundle \
  --assets-dest ios \
  --asset-catalog-dest ios/Images.xcassets

Custom Metro Configuration

Using Custom Config

npx react-native bundle \
  --entry-file index.js \
  --config metro.production.config.js \
  --bundle-output output.bundle

Metro Config Example

metro.production.config.js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');

const config = {
  transformer: {
    minifierConfig: {
      compress: {
        drop_console: true,
      },
    },
  },
};

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

Build Scripts

Add to package.json:
package.json
{
  "scripts": {
    "bundle:ios": "react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios",
    "bundle:android": "react-native bundle --entry-file index.js --platform android --dev false --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
    "bundle:both": "npm run bundle:ios && npm run bundle:android"
  }
}
Run:
npm run bundle:ios
npm run bundle:android
npm run bundle:both

Automation

Integrate with Build Process

iOS (Xcode Build Phase)

Add to Xcode Build Phases:
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh
This automatically bundles JavaScript during Xcode builds.

Android (Gradle)

Android builds automatically bundle JavaScript via Gradle tasks. Configure in android/app/build.gradle:
android/app/build.gradle
project.ext.react = [
    entryFile: "index.js",
    bundleAssetName: "index.android.bundle",
    bundleInDebug: false,
    bundleInRelease: true,
]

apply from: "../../node_modules/react-native/react.gradle"

Optimization

Remove Console Logs

metro.config.js
module.exports = {
  transformer: {
    minifierConfig: {
      compress: {
        drop_console: true,
      },
    },
  },
};

Inline Requires

metro.config.js
module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        inlineRequires: true,
      },
    }),
  },
};

Tree Shaking

Ensure imports are ES6 modules:
// Good - tree-shakeable
import {func} from './utils';

// Bad - imports entire module
const {func} = require('./utils');

Troubleshooting

Bundle Too Large

Solution:
  1. Enable minification:
--minify true
  1. Use inline requires in Metro config
  2. Remove unused dependencies
  3. Use dynamic imports for large modules

Assets Not Found

Error: Missing images in bundled app Solution: Ensure --assets-dest points to correct directory:
  • iOS: ios/ or ios/YourApp/
  • Android: android/app/src/main/res/

Source Maps Invalid

Solution: Generate source map during same bundle command:
npx react-native bundle \
  --bundle-output out.bundle \
  --sourcemap-output out.bundle.map

Cache Issues

Solution:
npx react-native bundle --reset-cache ...

Hermes Compilation Failed

Solution: Ensure you’re using the correct hermesc binary for your platform and that the bundle was created with --unstable-transform-profile hermes.

Bundle Analysis

Check Bundle Size

ls -lh main.jsbundle

Analyze Bundle Contents

Use react-native-bundle-visualizer:
npx react-native-bundle-visualizer
Generates an interactive visualization of your bundle.

Environment Variables

Custom Entry File

ENTRY_FILE=index.production.js npx react-native bundle ...

Custom Node Options

NODE_OPTIONS="--max-old-space-size=4096" npx react-native bundle ...

Next Steps

Metro Config

Configure Metro bundler settings

Build Android

Build production Android apps

Build iOS

Build production iOS apps

Performance

Optimize bundle size and performance

Build docs developers (and LLMs) love