Config parser and resolver for Metro bundler with support for loading, merging, and validating configuration files.
npx @tessl/cli install tessl/npm-metro-config@0.83.0Metro Config is the configuration parser and resolver for Metro bundler. It provides utilities for loading, merging, and validating Metro configuration files from various sources, with comprehensive type definitions and sensible defaults for all Metro components.
npm install metro-configimport { getDefaultConfig, loadConfig, loadConfigFile, mergeConfig, resolveConfig } from "metro-config";For CommonJS:
const { getDefaultConfig, loadConfig, loadConfigFile, mergeConfig, resolveConfig } = require("metro-config");For type definitions:
import type { ConfigT, InputConfigT, YargArguments } from "metro-config";import { getDefaultConfig, loadConfig, mergeConfig } from "metro-config";
// Get default Metro configuration
const defaultConfig = await getDefaultConfig();
// Load config from file system (auto-discovery)
const userConfig = await loadConfig();
// Load config from specific path
const customConfig = await loadConfig({
config: './custom-metro.config.js'
});
// Merge configurations
const finalConfig = mergeConfig(defaultConfig, userConfig);
// Complete workflow example
async function setupMetroConfig() {
// 1. Get defaults for current project
const defaults = await getDefaultConfig();
// 2. Load user configuration
const userConfig = await loadConfig({
config: './metro.config.js',
port: 3000,
resetCache: true
});
// 3. Create platform-specific overrides
const webOverrides = {
resolver: {
unstable_conditionsByPlatform: {
web: ['browser', 'import']
}
}
};
// 4. Merge all configurations
const finalConfig = mergeConfig(defaults, userConfig, webOverrides);
return finalConfig;
}Metro Config is built around several key components:
Load Metro configuration from files, with automatic discovery and support for multiple formats. Handles async configuration functions and CLI argument overrides.
/**
* Loads Metro configuration from various sources with automatic discovery
* @param argvInput - CLI arguments and configuration options (optional)
* @param defaultConfigOverrides - Base config overrides (optional)
* @returns Promise resolving to complete Metro configuration
*/
function loadConfig(
argvInput?: YargArguments,
defaultConfigOverrides?: InputConfigT
): Promise<ConfigT>;
/**
* Resolves configuration file path and loads the config
* @param filePath - Explicit path to config file (optional)
* @param cwd - Current working directory for search (optional)
* @returns Promise resolving to config resolution result
*/
function resolveConfig(filePath?: string, cwd?: string): Promise<ResolveConfigResult>;
interface ResolveConfigResult {
filepath: string;
isEmpty: boolean;
config: (ConfigT => Promise<ConfigT>) | (ConfigT => ConfigT) | InputConfigT;
}Deep merge multiple Metro configurations with validation and type safety.
/**
* Deep merges multiple Metro configuration objects
* @param defaultConfig - Base configuration object
* @param configs - Additional configurations to merge (later configs take precedence)
* @returns Complete merged Metro configuration
*/
function mergeConfig<T: $ReadOnly<InputConfigT>>(
defaultConfig: T,
...configs: Array<InputConfigT>
): T;Generate sensible default configuration for Metro bundler with all required options.
/**
* Gets default Metro configuration with sensible defaults
* @param rootPath - Project root directory (optional, defaults to auto-detected)
* @returns Promise resolving to complete default Metro configuration
*/
function getDefaultConfig(rootPath?: string): Promise<ConfigT>;// Complete Metro configuration (read-only)
type ConfigT = $ReadOnly<{
cacheStores: CacheStoresConfigT,
cacheVersion: string,
maxWorkers: number,
projectRoot: string,
resolver: $ReadOnly<ResolverConfigT>,
serializer: $ReadOnly<SerializerConfigT>,
server: $ReadOnly<ServerConfigT>,
symbolicator: $ReadOnly<SymbolicatorConfigT>,
transformer: $ReadOnly<TransformerConfigT>,
watcher: $ReadOnly<WatcherConfigT>,
// ... other core config fields
}>;
// User input configuration (partial)
type InputConfigT = Partial<$ReadOnly<{
// All ConfigT fields as optional/partial
}>>;
// Alias for InputConfigT
type MetroConfig = InputConfigT;
// CLI arguments for configuration
type YargArguments = $ReadOnly<{
config?: string,
cwd?: string,
port?: string | number,
projectRoot?: string,
// ... other CLI options
}>;// Module resolution configuration
type ResolverConfigT = {
assetExts: $ReadOnlyArray<string>,
sourceExts: $ReadOnlyArray<string>,
platforms: $ReadOnlyArray<string>,
blockList: RegExp | Array<RegExp>,
// ... other resolver options
};
// Bundle serialization configuration
type SerializerConfigT = {
createModuleIdFactory: () => (path: string) => number,
getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>,
// ... other serializer options
};
// Code transformation configuration
type TransformerConfigT = {
assetPlugins: $ReadOnlyArray<string>,
asyncRequireModulePath: string,
assetRegistryPath: string,
babelTransformerPath: string,
dynamicDepsInPackages: 'throwAtRuntime' | 'reject',
enableBabelRCLookup: boolean,
enableBabelRuntime: boolean,
getTransformOptions: GetTransformOptions,
globalPrefix: string,
hermesParser: boolean,
minifierConfig: $ReadOnly<{
mangle: $ReadOnly<{toplevel: boolean}>,
output: $ReadOnly<{
ascii_only: boolean,
quote_style: number,
wrap_iife: boolean,
}>,
sourceMap: $ReadOnly<{includeSources: boolean}>,
toplevel: boolean,
compress: $ReadOnly<{reduce_funcs: boolean}>,
}>,
minifierPath: string,
optimizationSizeLimit: number,
transformVariants: {+[name: string]: Partial<ExtraTransformOptions>},
publicPath: string,
allowOptionalDependencies: boolean,
unstable_allowRequireContext: boolean,
unstable_dependencyMapReservedName: ?string,
unstable_disableModuleWrapping: boolean,
unstable_disableNormalizePseudoGlobals: boolean,
unstable_renameRequire: boolean,
unstable_compactOutput: boolean,
unstable_memoizeInlineRequires: boolean,
unstable_workerThreads: boolean,
};type ExtraTransformOptions = $ReadOnly<{
preloadedModules?: $ReadOnly<{[path: string]: true}> | false,
ramGroups?: $ReadOnlyArray<string>,
transform?: $ReadOnly<{
experimentalImportSupport?: boolean,
inlineRequires?: boolean | $ReadOnly<{blockList: $ReadOnly<{[string]: true}>}>,
nonInlinedRequires?: $ReadOnlyArray<string>,
unstable_disableES6Transforms?: boolean,
unstable_memoizeInlineRequires?: boolean,
unstable_nonMemoizedInlineRequires?: $ReadOnlyArray<string>,
}>,
}>;
type GetTransformOptions = (
entryPoints: $ReadOnlyArray<string>,
options: GetTransformOptionsOpts,
getDependenciesOf: (string) => Promise<Array<string>>,
) => Promise<Partial<ExtraTransformOptions>>;
type GetTransformOptionsOpts = {
dev: boolean,
hot: true, // @deprecated Always true
platform: ?string,
};