wwwwwwwwwwwwwwwwwww

Metro Mode

Using Metro bundler for more stable native builds

Overview

One supports using Metro as the bundler for native builds, providing a more stable and battle-tested bundling experience. While the default Vite bundler for native is experimental, Metro mode offers production-ready stability by leveraging React Native's standard bundler.

Why Use Metro Mode?

  • Production Stability: Metro is the official React Native bundler with years of production use
  • Better Compatibility: Works seamlessly with all React Native packages and libraries
  • Familiar Tooling: If you're coming from standard React Native development, Metro works as expected
While Metro mode provides stability today, the One team is actively working on bringing Rolldown support to Vite mode and developing it to be production-ready.

Enabling Metro Mode

Configure the native bundler to Metro in your vite.config.ts:

vite.config.ts

import type { UserConfig } from 'vite'
import { one } from 'one/vite'
export default {
plugins: [
one({
native: {
// Enable Metro bundler for native builds
bundler: 'metro',
},
}),
],
} satisfies UserConfig

Limitations

When using Metro mode, only some of the Vite features are supported. One provides only a subset of Vite functionality in Metro mode to maintain compatibility and stability.

Metro mode intentionally supports only a subset of Vite configurations and features. This approach helps avoid implementation differences between Vite and Metro that could cause compatibility issues with React Native packages.
We are actively working on expanding Vite feature support, but for any features we don't yet provide through Vite configuration, you can always use the standard React Native way to change the configuration using babel.config.js and metro.config.js.

Only the following Vite features and configurations are supported in Metro mode for now:

  • import.meta.env Built-in Constants

    Partially Supported

    : supported but may not work as expected for web specific variables.
  • import.meta.env Env Variables

    Supported

  • tsconfig-paths

    Partially Supported

    : As one automatically configures vite-tsconfig-paths to support path mappings defined in tsconfig.json for your project, the same applies to Metro mode. However, if you are using the vite-tsconfig-paths plugin manually, the custom options you provide there will not be applied for Metro.

Configuration

By default, the Metro bundler is configured with Expo's defaults.

We recommend using the standard Vite way for configuring if possible, as it provides a more consistent experience across web and native builds, and will be more future-proof to switch between bundlers.

Like ordinary React Native apps, you can still configure Metro using standard configuration files:

babel.config.js - Configure Babel transformations for your JavaScript/TypeScript code:

babel.config.js

module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};

metro.config.js - Configure more advanced Metro bundler settings, such as resolver, transformations, or watcher options:

metro.config.js

const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
module.exports = config;

These configuration files work exactly as they would in a standard React Native project, giving you full control over the bundling process.

Performance

Metro mode is designed for production stability, but it may not match the performance of Vite as it is not optimized for speed, and is using Babel instead of SWC for transformations. However, we observed that Metro mode somehow provides better memory efficiency.

Edit this page on GitHub.