Metro Bundler
raw JSON → 0.45.6-vjpr.3 verified Sat Apr 25 auth: no javascript
Metro is the default JavaScript bundler for React Native, optimized for sub-second reload cycles and fast startup. Current stable version is 0.84.3 (released 2025-03-01), following a monthly release cadence. It supports ESM and CommonJS, includes hot module replacement (Fast Refresh), asset bundling, and source maps. Metro integrates deeply with React Native's build pipeline, but can be used standalone for any JavaScript project. Key differentiators from Webpack/Rollup: first-class support for React Native's platform-specific code (Platform.OS), inline require, and transformer caching.
Common errors
error Error: Could not resolve module 'react-native' ↓
cause Missing react-native dependency or misconfigured module resolution.
fix
Add react-native to package.json and run npm install. If using monorepo, ensure Metro's watchFolders includes the root.
error TypeError: Metro.loadConfig is not a function ↓
cause Importing loadConfig from 'metro' instead of 'metro-config'.
fix
Use
import { loadConfig } from 'metro-config'. error Error: Cannot find module 'metro-react-native-babel-transformer' ↓
cause Metro cannot locate the Babel transformer. Missing dependency or misconfigured transformerPath.
fix
Install
npm install --save-dev metro-react-native-babel-transformer and set transformer.babelTransformerPath in config. error ParseError: 'import' and 'export' may only appear at the top level ↓
cause Using ESM syntax in a CommonJS file (no 'type':'module' or .mjs extension).
fix
Rename file to .mjs or add 'type':'module' to package.json. Alternatively, transpile with Babel.
error Error: Opening IPC connection to Metro server failed ↓
cause Metro server not running or port conflict.
fix
Start Metro with
npx react-native start or set server.port in config. Kill other processes on port 8081. Warnings
breaking Node v21 and v23 support dropped. Minimum Node v20.19 LTS. ↓
fix Upgrade Node.js to v20.19 or later, or v22 LTS.
breaking ESM-only export from 'metro' requires dynamic import or native ESM. CommonJS require no longer works. ↓
fix Use import() or set type: module in package.json. Alternatively, downgrade to Metro 0.79.x.
deprecated `server.enhanceMiddleware` deprecated. Use `server.use` instead. ↓
fix Replace `enhanceMiddleware` with server.use in metro.config.js.
gotcha Config file must export a plain object or a function returning an object. Async configs supported since 0.83.3, but accidental Promise rejection breaks startup. ↓
fix Ensure config export is synchronous or wraps errors. Use `metro.config.js` (CJS) or `metro.config.mjs` (ESM).
gotcha Platform-specific file extensions (`.ios.js`, `.android.js`) are resolved by Metro, not Babel. Misconfigured resolver may miss files. ↓
fix Add custom resolver if needed. Do not rely on Babel plugins for platform-specific resolution.
deprecated `metro-react-native-babel-preset` was previously a separate package; now bundled with Metro. Installing separately may cause version conflicts. ↓
fix Remove explicit dependency on `metro-react-native-babel-preset` and rely on Metro's built-in preset.
Install
npm install metro-pnpm yarn add metro-pnpm pnpm add metro-pnpm Imports
- metro default wrong
const Metro = require('metro')correctimport Metro from 'metro' - mergeConfig wrong
import { mergeConfig } from 'metro'correctimport { mergeConfig } from 'metro-config' - MetroConfig wrong
interface MetroConfig { ... }correctimport type { MetroConfig } from 'metro-config' - require wrong
const Metro = require('metro')correct// Not used; Metro is a dev tool invoked via CLI or API
Quickstart
import Metro from 'metro';
import { loadConfig, mergeConfig } from 'metro-config';
const config = await loadConfig();
const updatedConfig = mergeConfig(config, {
transformer: {
babelTransformerPath: require.resolve('metro-react-native-babel-transformer'),
},
});
const { bundle } = await Metro.runBuild(updatedConfig, {
entry: 'index.js',
out: '/tmp/bundle.js',
platform: 'android',
dev: true,
});
console.log('Bundle built!');