Metro
website·Indexed 35 days ago
https://metrobundler.dev/The JavaScript bundler for React Native. Metro takes an entry file and various options to produce a single JavaScript bundle, featuring a module resolution algorithm, built-in cache stores, and support for Package Exports. It provides a CLI for bundling and a programmatic API for loading configurations and compiling files.
What's inside Metro
- Metro is the default JavaScript bundler for React Native. It is designed to be fast, scalable (supporting thousands of modules in a single application), and is integrated to work with every React Native project out of the box. Its primary goals are sub-second reload cycles, fast startup, and quick bundling speeds.
Overview of Package Exports in Metro
Package Exports allow npm packages to specify entry points and subpath mappings via theexportsfield inpackage.json. This allows packages to define which files are externally importable and provide different targets based on conditions (e.g., browser vs Node.js, orimportvsrequire). Support is enabled by default in Metro since version 0.82 (React Native 0.79).Overview of Metro Module Resolution
Module resolution is the build-time process of translating module names into absolute module paths. Metro uses a version of Node's module resolution algorithm but adds several specific features:
- Haste: An opt-in system to import modules by a globally unique name regardless of project structure.
- Platform Extensions: Support for platform-specific JavaScript modules (e.g.,
.ios.js,.android.js). - Asset Extensions: Automatic selection of image assets based on device screen density.
- Custom Resolvers: The ability for integrators to provide a custom resolver implementation to override default behavior.
Understand the `x_facebook_sources` source map extension
Metro includes a vendor-specific field
x_facebook_sourcesin its source maps to encode metadata about source files (e.g., AST analysis results). This allows debuggers and JS engines to access analysis without parsing the original source code.Key characteristics:
- It is a list of optional metadata tuples.
- The i-th tuple (
x_facebook_sources[i]) corresponds to the source file atsources[i]. - If the list is shorter than
sources, it is treated as if padded withnullvalues. - In nested/indexed source maps, it appears within sections that have a
sourcesfield.
Tooling Note: If you are building a tool that modifies source maps, you must ensure
x_facebook_sources[i]continues to correspond tosources[i]. If this synchronization cannot be guaranteed, thex_facebook_sourcesfield should be deleted from the output.Understand Metro bundling module identification
During the bundling process, every module is assigned a numeric ID. Consequently, dynamic requires are not supported because requires are replaced by these numeric versions to retrieve the corresponding module code.Understand the Metro bundling process
Metro is a JavaScript bundler that converts an entry file and its dependencies into a single JavaScript bundle. The process consists of three primary stages:
- Resolution: Metro uses a resolver to build a dependency graph of all modules required from the entry point. This stage typically runs in parallel with transformation.
- Transformation: A transformer transpiles each module into a format compatible with the target platform (e.g., React Native). This process is parallelized across available CPU cores.
- Serialization: Once all modules are transformed, a serializer combines them into one or more final JavaScript bundle files.
Customize Metro bundling stages via modules
Metro's architecture is modular, splitting the bundling flow into three distinct components: the resolver, the transformer, and the serializer. Because these are separate modules, they can be swapped out or customized to meet specific project requirements.Install Metro
Install Metro and its core components using npm or yarn.# Using npm npm install --save-dev metro metro-core # Using yarn yarn add --dev metro metro-coreImplement a custom JavaScript transformer for Metro
The JavaScript transformer (configured viababelTransformerPath) is used to manipulate JS code, typically by calling Babel. A transformer must export atransformmethod and can optionally export agetCacheKeymethod to manage caching across different transformers.Configure module resolution extensions and main fields
Metro uses the following properties to determine how to locate modules:
sourceExts: An ordered list of file extensions to attempt when a module path does not exist on disk.mainFields: An ordered list of fields inpackage.jsonused to resolve a package's main entry point, following the "browser" field spec.
Use Plain bundle for browser environments
The Plain bundle is the standard bundling format where all files are wrapped in a function call and added to a global file. This format is intended for environments that expect a JavaScript-only bundle, such as web browsers. To trigger a build of this type, require the entry point using the.bundleextension.Use TypeScript for Metro configuration
Metro supports native TypeScript configuration files (
.*ts).- For Node.js 22.18.0+ or 24.0.0+, erasable TypeScript is supported out of the box.
- For Node.js versions older than 22.18.0, you must use the
--experimental-strip-typesflag.