Implementation of Metro's resolution logic for JavaScript modules, assets, and packages within React Native and Metro bundler projects.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The ResolutionContext provides all the configuration settings, file system operations, and helper functions needed for module resolution. It serves as the central configuration object that controls how the resolver behaves.
The main configuration interface for the resolver.
interface ResolutionContext {
/** Whether to allow Haste module resolution */
readonly allowHaste: boolean;
/** File extensions considered as assets */
readonly assetExts: ReadonlyArray<string>;
/** File extensions considered as source files */
readonly sourceExts: ReadonlyArray<string>;
/** Options passed to custom resolvers */
readonly customResolverOptions: CustomResolverOptions;
/** Whether to disable hierarchical node_modules lookup */
readonly disableHierarchicalLookup: boolean;
/** Function to check if a file exists (deprecated, prefer fileSystemLookup) */
readonly doesFileExist: DoesFileExist;
/** Additional node_modules paths for resolution */
readonly extraNodeModules?: { [key: string]: string };
/** Function to perform file system lookups */
readonly fileSystemLookup: FileSystemLookup;
/** Function to parse package.json files */
readonly getPackage: (packageJsonPath: string) => PackageJson | null;
/** Function to get package info for a module path (deprecated) */
readonly getPackageForModule: (absoluteModulePath: string) => PackageForModule | null;
/** Dependency descriptor for diagnostic purposes */
readonly dependency?: any;
/** Whether the dependency was declared with ESM import syntax */
readonly isESMImport?: boolean;
/** Ordered list of package.json fields to check for main entry point */
readonly mainFields: ReadonlyArray<string>;
/** Path of the module requesting the resolution */
readonly originModulePath: string;
/** Global node_modules paths to search */
readonly nodeModulesPaths: ReadonlyArray<string>;
/** Whether to prefer .native files over platform-specific files */
readonly preferNativePlatform: boolean;
/** Function to resolve asset files */
readonly resolveAsset: ResolveAsset;
/** Function to redirect module paths */
readonly redirectModulePath: (modulePath: string) => string | false;
/** Function to resolve Haste modules */
readonly resolveHasteModule: (name: string) => string | undefined;
/** Function to resolve Haste packages */
readonly resolveHastePackage: (name: string) => string | undefined;
/** Custom resolver function */
readonly resolveRequest?: CustomResolver;
/** Condition names for package exports resolution */
unstable_conditionNames: ReadonlyArray<string>;
/** Platform-specific condition names */
unstable_conditionsByPlatform: Readonly<{ [platform: string]: ReadonlyArray<string> }>;
/** Whether to enable package.json exports field support */
unstable_enablePackageExports: boolean;
/** Function to log warnings */
unstable_logWarning: (message: string) => void;
}Functions that integrate with the file system and package resolution.
/** Check if a file exists at the given path */
type DoesFileExist = (filePath: string) => boolean;
/** Perform file system lookup with type information */
type FileSystemLookup = (
absoluteOrProjectRelativePath: string
) => { exists: false } | { exists: true; type: 'f' | 'd'; realPath: string };
/** Resolve asset files in a directory */
type ResolveAsset = (
dirPath: string,
assetName: string,
extension: string
) => ReadonlyArray<string> | undefined;Configuration options for custom resolvers.
type CustomResolverOptions = Readonly<{
[option: string]: unknown;
}>;Helper function to create a ResolutionContext with default settings.
/**
* Helper function to create a ResolutionContext with default values
* @param context - Partial context with custom overrides
* @param dependency - Dependency information for diagnostics
* @returns Complete ResolutionContext
*/
function createDefaultContext(
context: Partial<ResolutionContext>,
dependency: any
): ResolutionContext;Usage Examples:
const { createDefaultContext } = require("metro-resolver");
// Create context with common settings
const context = createDefaultContext({
allowHaste: false,
assetExts: ['png', 'jpg', 'gif', 'webp'],
sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json'],
mainFields: ['browser', 'main', 'module'],
originModulePath: '/app/src/index.js',
nodeModulesPaths: ['/app/node_modules'],
fileSystemLookup: (path) => {
const fs = require('fs');
try {
const stats = fs.lstatSync(path);
return {
exists: true,
type: stats.isDirectory() ? 'd' : 'f',
realPath: fs.realpathSync(path)
};
} catch {
return { exists: false };
}
},
getPackage: (packagePath) => {
try {
return require(packagePath);
} catch {
return null;
}
},
resolveAsset: (dirPath, name, ext) => {
// Custom asset resolution logic
return [`${dirPath}/${name}${ext}`];
},
unstable_enablePackageExports: true,
unstable_logWarning: console.warn
}, null);The context provides abstracted file system operations for flexibility.
interface FileSystemLookupResult {
exists: boolean;
type?: 'f' | 'd';
realPath?: string;
}Usage Example:
const context = {
// ... other config
fileSystemLookup: (path) => {
const fs = require('fs');
try {
const stats = fs.lstatSync(path);
return {
exists: true,
type: stats.isDirectory() ? 'd' : 'f',
realPath: fs.realpathSync(path)
};
} catch (error) {
return { exists: false };
}
}
};Functions for working with package.json files and package structure.
interface PackageJson {
readonly name?: string;
readonly main?: string;
readonly exports?: string | ExportMap;
readonly imports?: ExportMap;
readonly browser?: string | { [key: string]: string | false };
readonly module?: string;
}
interface PackageInfo {
readonly packageJson: PackageJson;
readonly rootPath: string;
}
interface PackageForModule extends PackageInfo {
readonly packageRelativePath: string;
}Controls the order of package.json fields checked for entry points.
Common Configurations:
// Browser-first (for web bundling)
mainFields: ['browser', 'module', 'main']
// Node.js-first
mainFields: ['main', 'module']
// React Native
mainFields: ['react-native', 'browser', 'main']Settings for handling platform-specific resolution.
interface PlatformConfiguration {
/** Whether to prefer .native files over platform-specific files */
preferNativePlatform: boolean;
/** Condition names for exports resolution */
unstable_conditionNames: ReadonlyArray<string>;
/** Platform-specific condition names */
unstable_conditionsByPlatform: Readonly<{ [platform: string]: ReadonlyArray<string> }>;
}Usage Example:
const context = {
// ... other config
preferNativePlatform: true,
unstable_conditionNames: ['import', 'require'],
unstable_conditionsByPlatform: {
ios: ['react-native', 'ios', 'native', 'import'],
android: ['react-native', 'android', 'native', 'import'],
web: ['browser', 'import']
}
};Settings for Haste module system integration.
interface HasteConfiguration {
/** Whether to allow Haste module resolution */
allowHaste: boolean;
/** Function to resolve Haste modules by name */
resolveHasteModule: (name: string) => string | undefined;
/** Function to resolve Haste packages by name */
resolveHastePackage: (name: string) => string | undefined;
}Settings for asset file resolution.
interface AssetConfiguration {
/** File extensions considered as assets */
assetExts: ReadonlyArray<string>;
/** Function to resolve asset files */
resolveAsset: ResolveAsset;
}Common Asset Extensions:
assetExts: [
'png', 'jpg', 'jpeg', 'gif', 'webp', 'svg',
'mp4', 'webm', 'wav', 'mp3', 'm4a', 'aac',
'otf', 'ttf', 'woff', 'woff2'
]