Skip to content
useffect.sh
Book 30 min with a senior
Tooling

Metro

React Native’s JavaScript bundler: it resolves, transforms, and serializes your code into a bundle, and runs the dev server.

Definition

Metro is the JavaScript bundler for React Native, maintained by Meta. Starting from an entry file, it builds the graph of every imported module, transforms each one with Babel so it runs on the target engine, then serializes them into one or more bundle files. Those three phases, resolution, transformation, and serialization, can each be swapped through configuration. In development, Metro is also the server that serves the bundle to the app, pushes edits through Fast Refresh, and relays the React Native DevTools connection. In release, it produces the bundle Hermes compiles to bytecode. It plays for React Native the role Vite or webpack play on the web, with its own constraints: several platforms from one codebase (.ios.tsx, .android.tsx, .web.tsx files), native assets, and an aggressive cache. An “Unable to resolve module” error at startup comes from it.

In a real app

The entry point is metro.config.js (or metro.config.mts since Metro 0.87, shipped from React Native 0.87), which extends getDefaultConfig from expo/metro-config or @react-native/metro-config. A project that does not start from that default, or that copied a config from three years ago, misses everything added since: package exports resolution, monorepo support, SVG assets, and so on. The rule I apply: custom config should fit in a few lines and every line should have a comment saying why.

Resolution problems are the most frequent. A module reported missing while it sits in node_modules usually comes from the cache (npx expo start --clear), a duplicated version in a monorepo, or a package exports field Metro reads differently from Node. .native.ts and .web.ts files are the right way to split code per platform; a Platform.OS guarding a require gets in the way of tree shaking on web export.

Metro itself has moved a lot: resolution announced as around 15x faster with React Native 0.76, source map generation twice as fast and half the memory with Metro 0.87. If a project’s dev server feels slow, the first thing to check is the Metro version actually installed (npm ls metro), not the config.

Our services on this

Sources

All 35 glossary terms

One of these is blocking your app?

30 minutes with a senior to look at the problem in your code. Free.