Metro Bundler for React Native
Metro is the JavaScript bundler specifically designed for React Native applications, providing optimized bundling, hot module reloading (HMR), and Fast Refresh capabilities crucial for efficient mobile development workflows. It is currently at version 0.84.3 and typically sees frequent minor releases, incorporating new features, bug fixes, and performance improvements. Key differentiators include its deep integration with the React Native ecosystem, advanced caching mechanisms for fast rebuilds, and robust support for various configuration options, including CommonJS, ESM, and TypeScript configuration files. Metro focuses on delivering a high-performance and streamlined developer experience, enabling rapid iteration cycles for large-scale React Native projects. It requires Node.js versions ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0.
Common errors
-
Error: Requires Node.js ^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0
cause Metro is being run with an incompatible or unsupported Node.js version.fixUpgrade or downgrade your Node.js installation to meet the specified engine requirements (`^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0`). -
Error: The transform cache was not invalidated correctly.
cause Metro's transformer cache did not correctly include user-defined Babel configuration, leading to stale bundles or incorrect transformations.fixUpgrade Metro to `v0.83.6` or newer. If an immediate upgrade is not feasible, try clearing Metro's cache manually by running `npx react-native start --reset-cache` or `npx metro serve --reset-cache`. -
Metro config file not found or is invalid.
cause Metro could not locate `metro.config.js` (or `.mjs`, `.ts`) in the expected locations, or the file contains syntax errors, or does not export a valid configuration object/promise.fixVerify that `metro.config.js` exists in the project root or `.config/` directory. Check the file for syntax errors and ensure it exports a valid Metro configuration object or a promise that resolves to one. Ensure any required paths are correctly resolved. -
TypeError: Cannot read properties of undefined (reading 'transform') (or similar during bundling)
cause This often indicates an issue with the Babel transformer configuration, such as an incorrect `babelTransformerPath` or missing `metro-react-native-babel-transformer` package.fixEnsure `metro-react-native-babel-transformer` is installed (`npm install metro-react-native-babel-transformer`) and `babelTransformerPath` in `metro.config.js` correctly points to its resolved path (`require.resolve('metro-react-native-babel-transformer')`).
Warnings
- breaking Metro `v0.84.0` introduced breaking changes by dropping support for older Node.js versions. Specifically, Node.js v21, v23, and LTS minors released before v20.19 are no longer supported.
- gotcha TypeScript type declarations have intermittently faced issues with publication in certain minor releases (e.g., in v0.83.x before v0.83.5 and v0.84.x before v0.84.2), leading to missing types or compilation errors in TypeScript projects.
- gotcha Enabling Metro's HTTPS server via `config.server.tls` (added in `v0.83.5` and `v0.84.1`) requires correctly configured SSL `key` and `cert` paths. Incorrect paths or malformed files will prevent the server from starting.
- gotcha Regressions in config file loading, such as issues with config files exporting promises or incorrect merging of multiple partial configs, have been observed and fixed in earlier `v0.83.x` releases. Using complex config logic on older versions might lead to unexpected behavior.
- gotcha Support for TypeScript `metro.config.ts` files (introduced in `v0.83.2`) relies on the underlying Node.js or Bun version's native TypeScript support. If your environment does not natively support `.ts` execution, you may need additional setup (e.g., `ts-node`).
Install
-
npm install metro -
yarn add metro -
pnpm add metro
Imports
- getDefaultConfig
const { getDefaultConfig } = require('metro');import { getDefaultConfig } from 'metro-config'; - mergeConfig
const { mergeConfig } = require('metro/config');import { mergeConfig } from 'metro-config'; - MetroConfig
import type { MetroConfig } from 'metro-config';
Quickstart
import path from 'path';
import { getDefaultConfig } from 'metro-config';
/**
* Metro configuration for a React Native project.
* See: https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = (async () => {
const { resolver: { sourceExts, assetExts } } = await getDefaultConfig(__dirname);
return {
transformer: {
babelTransformerPath: require.resolve('metro-react-native-babel-transformer'),
enableBabelRCLookup: true,
// Optionally customize babel transformer options
// getTransformOptions: async () => ({
// transform: {
// experimentalImportSupport: false,
// inlineRequires: true,
// },
// }),
},
resolver: {
assetExts: [...assetExts, 'gltf', 'glb', 'bin', 'webp', 'mp3', 'mp4'],
sourceExts: [...sourceExts, 'mjs', 'cjs', 'ts', 'tsx'],
},
server: {
port: process.env.METRO_PORT ? parseInt(process.env.METRO_PORT, 10) : 8081,
// Enable HTTPS server with your own key and certificate:
// https: {
// key: path.resolve(__dirname, './ssl/key.pem'),
// cert: path.resolve(__dirname, './ssl/cert.pem'),
// },
},
// Add additional directories to watch for changes, useful in monorepos.
watchFolders: [
// path.resolve(__dirname, '../../packages/my-shared-components'),
],
// Cache configuration (defaults to FileStore).
cacheStores: [],
};
})();
module.exports = config;