or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

async-loading.mdhmr-client.mdindex.mdrequire-polyfill.md
tile.json

tessl/npm-metro-runtime

Module required for evaluating Metro bundles with async loading and HMR support.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/metro-runtime@0.83.x

To install, run

npx @tessl/cli install tessl/npm-metro-runtime@0.83.0

index.mddocs/

Metro Runtime

Metro Runtime provides essential runtime modules required for evaluating and executing Metro bundles in React Native applications. It enables asynchronous module loading, Hot Module Replacement (HMR), and includes necessary runtime polyfills for cross-platform development.

Package Information

  • Package Name: metro-runtime
  • Package Type: npm
  • Language: JavaScript (with Flow types)
  • Installation: Automatically included by Metro bundler (no manual installation required)

Core Imports

Metro Runtime modules are automatically included by Metro bundler and typically not imported manually. When needed for custom implementations:

// Async module loading (typically available globally as require.importAll)
const asyncRequire = require("metro-runtime/modules/asyncRequire");

// Hot Module Replacement client (development only)
const HMRClient = require("metro-runtime/modules/HMRClient");

// Module stubs for optimization
const emptyModule = require("metro-runtime/modules/empty-module"); // exports {}
const nullModule = require("metro-runtime/modules/null-module"); // exports null

// Core require polyfill (injected globally by Metro bundler)
// Available as global.__r, global.__d, etc.
require("metro-runtime/polyfills/require");

// Package metadata access
const packageInfo = require("metro-runtime/package.json");

Package Metadata Access

The package.json file is exposed as a direct export for accessing package metadata:

// Package metadata access
const packageInfo = require("metro-runtime/package.json");

Private Module Access

Metro Runtime exposes private modules for internal Metro bundler usage via wildcard patterns:

  • ./private/* - Maps to ./src/*.js
  • ./src/*.js - Direct access to source files
  • ./src/* - Alternative access pattern

These are typically used by Metro bundler itself and not intended for direct application usage.

Basic Usage

Metro Runtime is typically used automatically by Metro bundler, but can be used directly for custom bundling scenarios:

const asyncRequire = require("metro-runtime/modules/asyncRequire");
const HMRClient = require("metro-runtime/modules/HMRClient");

// Load a module asynchronously with bundle splitting support
const loadFeature = async () => {
  const featureModule = await asyncRequire(
    42, // module ID
    { 42: "/bundles/feature.bundle.js" } // path mapping
  );
  return featureModule;
};

// Set up HMR client for development
const client = new HMRClient("ws://localhost:8081/hot");
client.enable();

client.on("update", (update) => {
  console.log("Hot update received:", update);
});

Architecture

Metro Runtime is built around several key components:

  • Async Loading System: Handles dynamic imports and bundle splitting with support for lazy loading
  • HMR Client: WebSocket-based client for receiving and applying hot updates during development
  • Module System Polyfills: Cross-platform require implementation with React Native compatibility
  • Module Stubs: Empty and null modules for build optimization and conditional loading
  • React Fast Refresh Integration: Component-level hot reloading with state preservation

Capabilities

Asynchronous Module Loading

Core functionality for loading modules asynchronously with bundle splitting support. Enables dynamic imports and code splitting in Metro bundles.

// Async module loading with bundle splitting support
function asyncRequire(moduleID: number, paths: ?DependencyMapPaths, moduleName?: string): Promise<any>;

// Synchronous version that may return promise if bundle loading required
asyncRequire.unstable_importMaybeSync = function(moduleID: number, paths: ?DependencyMapPaths): Promise<any> | any;

// Pre-loads bundle without executing module
asyncRequire.prefetch = function(moduleID: number, paths: ?DependencyMapPaths, moduleName?: string): void;

type DependencyMapPaths = ?$ReadOnly<{[moduleID: number | string]: mixed}>;

Async Loading

Hot Module Replacement Client

WebSocket-based client for receiving and applying hot updates during development. Provides real-time code updates without losing application state.

// Hot Module Replacement WebSocket client
class HMRClient extends EventEmitter {
  constructor(url: string);
  close(): void;
  send(message: string): void;
  enable(): void;
  disable(): void;
  isEnabled(): boolean;
  hasPendingUpdates(): boolean;
}

type SocketState = 'opening' | 'open' | 'closed';

HMR Client

Require System Polyfill

Core Metro require system implementation with module loading, HMR support, and development utilities. Provides cross-platform module resolution and loading.

// Core Metro require function (available as global.__r)
function metroRequire(moduleId: ModuleID | VerboseModuleNameForDev, maybeNameForDev?: string): Exports;

// Module definition function (available as global.__d)
function define(factory: FactoryFn, moduleId: number, dependencyMap?: DependencyMap, verboseName?: string, inverseDependencies?: InverseDependencyMap): void;

// Enhanced import functions
metroRequire.importDefault = function(moduleId: ModuleID | VerboseModuleNameForDev): any | Exports;
metroRequire.importAll = function(moduleId: ModuleID | VerboseModuleNameForDev): any | Exports | {[string]: any};

// Module ID utilities for segmented bundles
metroRequire.unpackModuleId = function(moduleId: ModuleID): {localId: number, segmentId: number};
metroRequire.packModuleId = function(value: {localId: number, segmentId: number}): ModuleID;

type ModuleID = number;
type VerboseModuleNameForDev = string;
type Exports = any;

Require Polyfill

Module Stubs

Provides empty and null module stubs for build optimization and conditional loading scenarios.

// Empty module stub - exports empty object {}
const emptyModule = require("metro-runtime/modules/empty-module");

// Null module stub - exports null
const nullModule = require("metro-runtime/modules/null-module");

These stubs are used by Metro bundler for:

  • Tree shaking optimization: Replace unused modules with empty stubs
  • Conditional compilation: Provide placeholder modules for platform-specific code
  • Build size reduction: Replace heavy modules with lightweight stubs in certain contexts

Types

Core type definitions used across Metro Runtime:

type DependencyMapPaths = ?$ReadOnly<{[moduleID: number | string]: mixed}>;

type ModuleID = number;
type VerboseModuleNameForDev = string;
type Exports = any;
type RequireFn = (id: ModuleID | VerboseModuleNameForDev) => Exports;

type FactoryFn = (
  global: Object,
  require: RequireFn,
  metroImportDefault: RequireFn,
  metroImportAll: RequireFn,
  moduleObject: {exports: {...}, ...},
  exports: {...},
  dependencyMap: ?DependencyMap,
) => void;

// Module system types
type DependencyMap = $ReadOnly<ArrayIndexable<ModuleID> & {paths?: {[id: ModuleID]: string}}>;
type InverseDependencyMap = {[key: ModuleID]: Array<ModuleID>, ...};
type ArrayIndexable<T> = interface {+[indexer: number]: T};

// Bundle and module types
type ModuleMap = $ReadOnlyArray<[number, string]>;

type Bundle = {
  +modules: ModuleMap,
  +post: string,
  +pre: string,
};

type DeltaBundle = {
  +added: ModuleMap,
  +modified: ModuleMap,
  +deleted: $ReadOnlyArray<number>,
};

type BundleVariant =
  | {+base: true, +revisionId: string, ...Bundle}
  | {+base: false, +revisionId: string, ...DeltaBundle};

type BundleMetadata = {
  +pre: number,
  +post: number,
  +modules: $ReadOnlyArray<[number, number]>,
};

// HMR types  
type HmrUpdate = {
  +added: $ReadOnlyArray<HmrModule>,
  +deleted: $ReadOnlyArray<number>,
  +isInitialUpdate: boolean,
  +modified: $ReadOnlyArray<HmrModule>,
  +revisionId: string,
};

type HmrModule = {
  +module: [number, string],
  +sourceMappingURL: string,
  +sourceURL: string,
};

type FormattedError = {
  +type: string,
  +message: string,
  +errors: Array<{description: string, ...}>,
};

// HMR message types
type HmrMessage =
  | {+type: 'bundle-registered'}
  | {+type: 'update-start', +body: {+isInitialUpdate: boolean}}
  | {+type: 'update-done'}
  | {+type: 'update', +body: HmrUpdate}
  | {+type: 'error', +body: FormattedError};

type HmrClientMessage =
  | {+type: 'register-entrypoints', +entryPoints: Array<string>}
  | {+type: 'log', +level: 'trace' | 'info' | 'warn' | 'log' | 'group' | 'groupCollapsed' | 'groupEnd' | 'debug', +data: Array<mixed>, +mode: 'BRIDGE' | 'NOBRIDGE'}
  | {+type: 'log-opt-in'};

// Development types (DEV only)
type HotModuleReloadingData = {
  _acceptCallback: ?HotModuleReloadingCallback,
  _disposeCallback: ?HotModuleReloadingCallback,
  _didAccept: boolean,
  accept: (callback?: HotModuleReloadingCallback) => void,
  dispose: (callback?: HotModuleReloadingCallback) => void,
};

type HotModuleReloadingCallback = () => void;