Metro bundler

Edit this page

Learn about different Metro bundler configurations that can be customized.


Expo CLI uses Metro during npx expo start and npx expo export to bundle your JavaScript code and assets. Metro is built and optimized for React Native and used for large-scale applications such as Facebook and Instagram.

Customizing

You can customize the Metro bundler by creating a metro.config.js file at the root of your project. This file should export a Metro configuration that extends expo/metro-config. Import expo/metro-config instead of @expo/metro-config to ensure version consistency.

Run the following command to generate the template file:

Terminal
npx expo customize metro.config.js

The metro.config.js file looks as below:

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

const config = getDefaultConfig(__dirname);

module.exports = config;

See metro.config.js documentation for more information.

Assets

Metro resolves files as either source code or assets. Source code is JavaScript, TypeScript, JSON, and other files used by your application. Assets are images, fonts, and other files that should not be transformed by Metro. To accommodate large-scale codebases, Metro requires all extensions for both source code and assets to be explicitly defined before starting the bundler. This is done by adding the resolver.sourceExts and resolver.assetExts options to the Metro configuration. By default, the following extensions are included:

Adding more file extensions to assetExts

The most common customization is to include extra asset extensions to Metro.

In the metro.config.js file, add the file extension (without a leading .) to resolver.assetExts array:

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

const config = getDefaultConfig(__dirname);

config.resolver.assetExts.push(
  // Adds support for `.db` files for SQLite databases
  'db'
);

module.exports = config;

Aliases

Sometimes you want an import to be redirected to another module or file. This is called an alias. Due to the way Metro bundles for multiple platforms simultaneously, we recommend using a custom resolver to handle aliases.

In the following example, we'll add an alias for old-module to new-module:

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

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

const ALIASES = {
  'old-module': 'new-module',
};

config.resolver.resolveRequest = (context, moduleName, platform) => {
  // Ensure you call the default resolver.
  return context.resolveRequest(
    context,
    // Use an alias if one exists.
    ALIASES[moduleName] ?? moduleName,
    platform
  );
};

module.exports = config;

If you want to only apply the alias on a certain platform, you can check the platform argument:

metro.config.js
config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (platform === 'web') {
    // The alias will only be used when bundling for the web.
    return context.resolveRequest(context, ALIASES[moduleName] ?? moduleName, platform);
  }
  // Ensure you call the default resolver.
  return context.resolveRequest(context, moduleName, platform);
};

You will see the changes the next time you restart the dev server. Resolutions are never cached and do not need the --clear flag to update. If you use a transform-based system like babel-plugin-module-resolver, you will need to clear the cache to see changes applied.

Customizing Metro resolution

Learn more about advanced Metro resolving in your project.

Bundle splitting

From SDK 50, Expo CLI automatically splits bundles based on async imports (web-only).

This technique can be used with Expo Router to automatically split the bundle based on route files in the app directory. It will only load the code required for the current route, and defer loading additional JavaScript until the user navigates to different pages. See Async Routes for more information.

Tree shaking

Tree shaking

Learn about how Expo CLI optimizes production JavaScript bundles.

Minification

Minifying JavaScript

Learn about customizing the JavaScript minification process in Expo CLI with Metro bundler.

Web support

Expo CLI has support for bundling websites using Metro. This is the same bundler used for native apps, and it is designed to be universal across platforms. It is the recommended bundler for web projects in Expo SDK 50 and greater.

Expo webpack versus Expo Metro

If you previously wrote your website using the deprecated @expo/webpack-adapter, see the migration guide and comparison chart.

Adding Web support to Metro

Modify your app config to enable the feature using the expo.web.bundler field:

app.json
{
  "expo": {
    "web": {
      "bundler": "metro"
    }
  }
}

Development

To start the development server run the following command:

Terminal
npx expo start --web

Alternatively, press W in the Expo CLI terminal UI.

Static files

Expo's Metro implementation supports hosting static files from the dev server by putting them in the root public/ directory. It is similar to many other web frameworks.

When exporting with npx expo export, the contents of the public directory are copied into the dist/ directory. It means your app can expect to fetch these assets relative to the host URL. The most common example of this is the public/favicon.ico which is used by websites to render the tab icon.

You can overwrite the default index.html in Metro web by creating a public/index.html file in your project.

In the future, this will work universally across platforms with EAS Update hosting. Currently, the feature is web-only based on the static host used for the native app, for example, the legacy Expo service updates do not support this feature.

TypeScript

Expo's Metro config supports the compilerOptions.paths and compilerOptions.baseUrl fields in the project's tsconfig.json (or jsconfig.json) file. This enables absolute imports and aliases in the project. See TypeScript guide for more information.

This feature requires additional setup in bare projects. See the Metro setup guide for more information.

CSS

Metro web CSS guide

Learn how to use CSS in websites that are bundled with Expo CLI and Metro bundler.