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.

Tokens
14K
Snippets
59
Records
116
Agent score
71%

What's inside Metro

  1. Overview of the Metro JavaScript Bundler

    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.
  2. Overview of Package Exports in Metro

    Package Exports allow npm packages to specify entry points and subpath mappings via the exports field in package.json. This allows packages to define which files are externally importable and provide different targets based on conditions (e.g., browser vs Node.js, or import vs require). Support is enabled by default in Metro since version 0.82 (React Native 0.79).
  3. 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.
  4. Understand the `x_facebook_sources` source map extension

    Metro includes a vendor-specific field x_facebook_sources in 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 at sources[i].
    • If the list is shorter than sources, it is treated as if padded with null values.
    • In nested/indexed source maps, it appears within sections that have a sources field.

    Tooling Note: If you are building a tool that modifies source maps, you must ensure x_facebook_sources[i] continues to correspond to sources[i]. If this synchronization cannot be guaranteed, the x_facebook_sources field should be deleted from the output.

  5. 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.
  6. 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:

    1. 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.
    2. 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.
    3. Serialization: Once all modules are transformed, a serializer combines them into one or more final JavaScript bundle files.
  7. 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.
  8. Implement a custom JavaScript transformer for Metro

    The JavaScript transformer (configured via babelTransformerPath) is used to manipulate JS code, typically by calling Babel. A transformer must export a transform method and can optionally export a getCacheKey method to manage caching across different transformers.
  9. 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 in package.json used to resolve a package's main entry point, following the "browser" field spec.
  10. 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 .bundle extension.
  11. 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-types flag.