Why Metro?

Edit this page

Learn why Metro is the future of universal bundling in React Native and how it benefits developers.


Metro is the official bundler for Expo and React Native. It's a central build tool in the Expo framework. Bundlers comprise thousands of opinions and trade-offs. This document outlines the key reasons why Expo is developed around Metro and how it benefits developers.

Official Meta bundler

Metro is maintained by Meta, the maintainers of React, React Native, Yoga, and Hermes. It's used for developing some of the world's largest apps, ranging across all categories in the app stores.

By having first-class Metro support, we ensure Expo developers have continuity across Meta's tools and get instant access to emerging features. This includes:

  • React Fast Refresh was first introduced as a Metro feature in 2019. The React web community adopted it the following year via Webpack.
  • Transforming JavaScript to Hermes bytecode for instant native startup.
  • React Native Dev Tools, including first-class support for network and JS debugging, is exclusively available with Metro and Hermes.
  • React Compiler was initially rolled out as a Metro-compatible Babel plugin.

New and upcoming features that are planned to come to Metro include:

  • Compiling Flow code to native machine code with Static Hermes. Learn more in the Static Hermes talk by Tzvetan Mikov.
  • Data fetching, streaming, React Suspense, server rendering, and build-time static rendering with universal React Server Components for all platforms. Learn more in the Universal React Server Components talk at React Conf 2024.

The Expo team collaborates with Meta to develop Metro for Expo Router, adding features like file-based routing, web support, bundle splitting, tree shaking, CSS, DOM components, server components, and API routes.

Battle-tested at scale

Nearly every React Native app in the world uses Metro, making it a battle-tested solution optimized for large-scale projects. This makes it suitable for developers of all sizes, from hobbyists to large companies. Metro is designed specifically to handle large-scale Meta apps, which is why it has features such as native file watching with Watchman and shared remote caches.

On-demand processing

In development, Metro doesn't perform any platform-specific work until requested. This allows developers to work on large projects without paying a performance cost for the number of platforms they support. In conjunction with aggressive caching and async routes, developers can incrementally bundle only the parts of the app that they're actively working on.

Multi-dimensional

Unlike traditional bundlers, which create multiple instances to bundle server and client code, Metro maximizes resource reuse across platforms and environments (server, client, DOM components). This architecture is ideal for multiplatform and server development.

Reusable transform memoization

Metro is incremental and can create cached transform artifacts that can be used across machines. This enables large teams to reuse work from remote builders, a technique used at Meta for all large projects.

Optimized for custom runtimes

While other bundlers are designed around the static specification of web browsers, Metro is optimized for the flexibility of React Native. This enables features like bytecode compilation for faster app startup in production and will extend to Static Hermes, which will compile type information into machine code for native apps.

Cross-technology support

Expo leverages Metro's technology to create novel functionality like DOM components. This allows a React component in a native app to be dynamically bundled as an entire website with all the same defaults as the parent app, on-demand.

Native asset exports

Unlike traditional bundlers, where the end result is a fully hosted app, Metro's configuration options support exporting bundles to embed as native artifacts in standalone app binaries. This leverages OS-specific optimizations such as xcassets on Apple platforms.

Concurrent processing

All AST transformation in Metro is performed concurrently across all available threads, maximizing the use of hardware.

Comparison with other approaches

While Metro is designed for universal app development, it's often compared to other web-only bundlers. Here are some key differences:

Browser ESM versus bundling

While bundlers like Vite leverage built-in ESM support in the browser, this approach can lead to slower practical development times at medium to large scales due to thousands of cascading network requests. Metro performs bundling in local development, which is better suited for React Native's larger module count.

JavaScript versus native languages

Several bundlers are opting to write their core in Rust for performance reasons, but this comes with some trade-offs, such as more challenging contributions, patches, and development. Metro uses a mix of technologies based on the operation:

  • The core bundler and utilities are written in JS/Flow.
  • File watching is written in C++ via Watchman, with a JS fallback. Watchman is then used across projects on your computer.
  • AST is parsed with Hermes parser (WebAssembly) to a Babel-compatible format.
  • AST transformation is done with Babel. This maximizes developer customization.
  • Minification uses Hermes on native platforms and Terser (with optional ESBuild support) for web.
  • CSS parsing and minification is performed with LightningCSS (Rust).

This approach aligns with Meta and community tools while allowing easier debugging, profiling, and patching for developers.