Enhanced Resolve is a highly configurable async require.resolve function that provides sophisticated Node.js module resolution capabilities. It serves as the core resolution engine for webpack and offers extensive customization through plugins, custom file systems, and configuration options, supporting modern package.json features like exports fields and conditional exports.
npm install enhanced-resolveconst resolve = require("enhanced-resolve");ESM:
import resolve from "enhanced-resolve";TypeScript:
import resolve, {
ResolverFactory,
CachedInputFileSystem,
SyncAsyncFileSystemDecorator,
CloneBasenamePlugin,
LogInfoPlugin,
forEachBail,
type ResolveCallback,
type ResolveOptions,
type BaseFileSystem,
type FileSystem,
type SyncFileSystem
} from "enhanced-resolve";const resolve = require("enhanced-resolve");
// Simple async resolution
resolve(__dirname, "./some-module", (err, result) => {
if (err) console.error(err);
else console.log(result); // "/path/to/resolved/module.js"
});
// Sync resolution
const resolved = resolve.sync(__dirname, "./some-module");
console.log(resolved); // "/path/to/resolved/module.js" or false
// Custom resolver with options
const customResolve = resolve.create({
extensions: [".js", ".json", ".ts"],
alias: {
"@": "/src",
"utils": "/src/utils"
},
modules: ["node_modules", "custom_modules"]
});
customResolve(__dirname, "@/components/Button", (err, result) => {
console.log(result); // "/src/components/Button.js"
});Enhanced Resolve is built around several key architectural components:
Primary async and sync resolution functions with multiple calling patterns and customizable options.
// Main async resolver function with multiple overloads
function resolve(context, path, request, resolveContext, callback);
function resolve(context, path, request, callback);
function resolve(path, request, resolveContext, callback);
function resolve(path, request, callback);
// Sync resolver function
resolve.sync(context, path, request): string | false;
resolve.sync(path, request): string | false;Factory functions for creating custom resolvers with specific configuration options.
// Create custom async resolver
resolve.create(options: ResolveOptions): ResolverFunction;
// Create custom sync resolver
resolve.create.sync(options: ResolveOptions): SyncResolverFunction;Configurable file system abstraction with caching capabilities for performance optimization.
class CachedInputFileSystem {
constructor(fileSystem: BaseFileSystem, duration: number);
purge(what?: string | string[]): void;
}
class SyncAsyncFileSystemDecorator {
constructor(syncFileSystem: SyncFileSystem);
}Extensive plugin system with 27+ built-in plugins for handling aliases, modern package features, and custom resolution logic.
class CloneBasenamePlugin {
constructor(source: string, target: string);
apply(resolver: Resolver): void;
}
class LogInfoPlugin {
constructor(source: string);
apply(resolver: Resolver): void;
}Support for modern package.json features including exports/imports fields and conditional exports.
interface ResolveOptions {
exportsFields?: (string | string[])[];
importsFields?: (string | string[])[];
conditionNames?: string[];
}Utility functions for common operations during resolution.
/**
* Iterates through array with early bailout functionality
* @param array - Array to iterate through
* @param iterator - Iterator function called for each item
* @param callback - Final callback after completion or early bailout
*/
function forEachBail<T, Z>(
array: T[],
iterator: (item: T, callback: (err?: Error, result?: Z) => void, index: number) => void,
callback: (err?: Error, result?: Z, index?: number) => void
): void;type ResolveCallback = (
err: null | Error,
res?: string | false,
req?: ResolveRequest
) => void;
interface ResolveOptions {
alias?: AliasOptions | AliasOption[];
fallback?: AliasOptions | AliasOption[];
extensions?: string[];
modules?: string | string[];
mainFields?: (string | string[] | { name: string | string[]; forceRelative: boolean })[];
mainFiles?: string[];
fileSystem: FileSystem;
plugins?: Plugin[];
symlinks?: boolean;
unsafeCache?: boolean | Cache;
conditionNames?: string[];
exportsFields?: (string | string[])[];
importsFields?: (string | string[])[];
}
interface ResolveContext {
contextDependencies?: WriteOnlySet<string>;
fileDependencies?: WriteOnlySet<string>;
missingDependencies?: WriteOnlySet<string>;
log?: (str: string) => void;
}
interface ResolveRequest {
path: string | false;
context?: object;
request?: string;
descriptionFilePath?: string;
descriptionFileData?: JsonObject;
}
type AliasOptions = {
[key: string]: string | false | string[];
};
interface AliasOption {
name: string;
alias: string | false | string[];
onlyModule?: boolean;
}
interface JsonObject {
[key: string]: any;
}
interface WriteOnlySet<T> {
add(item: T): void;
}
interface FileSystem {
readFile(path: string, callback: (err: Error | null, data?: Buffer) => void): void;
readdir(path: string, callback: (err: Error | null, files?: string[]) => void): void;
readlink(path: string, callback: (err: Error | null, link?: string) => void): void;
stat(path: string, callback: (err: Error | null, stats?: any) => void): void;
}
interface SyncFileSystem {
readFileSync(path: string): Buffer;
readdirSync(path: string): string[];
readlinkSync(path: string): string;
statSync(path: string): any;
}
type BaseFileSystem = FileSystem & SyncFileSystem;