Support for modern package.json features including exports/imports fields and conditional exports, enabling compatibility with ES modules and conditional package resolution.
Support for the modern "exports" field that allows packages to define multiple entry points and conditional exports.
/**
* Configuration for exports field processing
*/
interface ResolveOptions {
/** List of exports fields to process (default: ["exports"]) */
exportsFields?: (string | string[])[];
/** Condition names for conditional exports */
conditionNames?: string[];
}Usage Examples:
const resolve = require("enhanced-resolve").create({
extensions: [".js", ".mjs", ".json"],
exportsFields: ["exports"],
conditionNames: ["import", "require", "node", "default"]
});
// Resolve a package with exports field
resolve(__dirname, "modern-package", (err, result) => {
console.log(result); // Resolved using exports field
});
// Package.json example that would be resolved:
const examplePackage = {
"name": "modern-package",
"exports": {
".": {
"import": "./esm/index.mjs",
"require": "./cjs/index.js",
"node": "./node/index.js",
"default": "./index.js"
},
"./utils": {
"import": "./esm/utils.mjs",
"require": "./cjs/utils.js"
},
"./package.json": "./package.json"
}
};Support for the "imports" field that allows packages to define internal import mappings.
/**
* Configuration for imports field processing
*/
interface ResolveOptions {
/** List of imports fields to process (default: ["imports"]) */
importsFields?: (string | string[])[];
/** Condition names for conditional imports */
conditionNames?: string[];
}Usage Examples:
const resolve = require("enhanced-resolve").create({
extensions: [".js", ".mjs"],
importsFields: ["imports"],
conditionNames: ["import", "require", "node", "default"]
});
// Package.json with imports field:
const packageWithImports = {
"name": "my-package",
"imports": {
"#utils/*": {
"import": "./src/utils/*.mjs",
"require": "./lib/utils/*.js"
},
"#config": {
"node": "./config/node.js",
"default": "./config/default.js"
}
}
};
// Internal imports would resolve:
// "#utils/string" -> "./src/utils/string.mjs" (ESM) or "./lib/utils/string.js" (CJS)
// "#config" -> "./config/node.js" (Node.js) or "./config/default.js" (other)Support for conditional exports based on environment, module system, and custom conditions.
/**
* Common condition names for different scenarios
*/
const CommonConditions = {
/** ES module imports */
IMPORT: "import",
/** CommonJS requires */
REQUIRE: "require",
/** Node.js environment */
NODE: "node",
/** Browser environment */
BROWSER: "browser",
/** Development mode */
DEVELOPMENT: "development",
/** Production mode */
PRODUCTION: "production",
/** Default fallback */
DEFAULT: "default"
};Usage Examples:
// Resolver for different environments
const nodeResolve = require("enhanced-resolve").create({
conditionNames: ["node", "import", "require", "default"],
exportsFields: ["exports"]
});
const browserResolve = require("enhanced-resolve").create({
conditionNames: ["browser", "import", "require", "default"],
exportsFields: ["exports"]
});
// Package with complex conditional exports:
const complexPackage = {
"exports": {
".": {
"node": {
"import": "./node/esm/index.mjs",
"require": "./node/cjs/index.js"
},
"browser": {
"import": "./browser/esm/index.mjs",
"require": "./browser/cjs/index.js"
},
"development": "./dev/index.js",
"production": "./prod/index.js",
"default": "./index.js"
},
"./server": {
"node": "./server/node.js",
"default": false // Not available outside Node.js
},
"./client": {
"browser": "./client/browser.js",
"default": false // Not available outside browser
}
}
};Support for pattern matching in exports and imports fields using wildcards.
/**
* Pattern matching examples in package.json
*/
const patternExamples = {
"exports": {
"./features/*": {
"import": "./esm/features/*.mjs",
"require": "./cjs/features/*.js"
},
"./locales/*": "./locales/*.json",
"./themes/*/index.css": "./themes/*/dist/index.css"
},
"imports": {
"#internal/*": "./src/internal/*.js",
"#utils/*": {
"import": "./src/utils/*.mjs",
"require": "./lib/utils/*.js"
}
}
};Usage Examples:
const resolve = require("enhanced-resolve").create({
exportsFields: ["exports"],
importsFields: ["imports"],
conditionNames: ["import", "require", "default"]
});
// These would resolve using pattern matching:
// "./features/auth" -> "./esm/features/auth.mjs" (ESM) or "./cjs/features/auth.js" (CJS)
// "./locales/en" -> "./locales/en.json"
// "./themes/dark/index.css" -> "./themes/dark/dist/index.css"Support for packages referencing themselves through their own exports field.
/**
* Self-reference configuration
*/
interface ResolveOptions {
/** Enable processing of self-references */
exportsFields?: string[];
/** Package name for self-reference resolution */
descriptionFiles?: string[]; // Usually ["package.json"]
}Usage Examples:
// Package can reference itself
const selfReferencePackage = {
"name": "my-library",
"exports": {
".": "./index.js",
"./utils": "./utils/index.js",
"./helpers/*": "./helpers/*.js"
}
};
// Inside the package, these imports work:
// import utils from "my-library/utils";
// import { helper } from "my-library/helpers/string";
const resolve = require("enhanced-resolve").create({
exportsFields: ["exports"],
descriptionFiles: ["package.json"]
});Proper error handling for invalid exports and imports configurations.
/**
* Common errors when working with modern package features
*/
const ModernPackageErrors = {
/** Package subpath not defined in exports */
PACKAGE_PATH_NOT_EXPORTED: "Package subpath './path' is not defined by 'exports'",
/** Invalid package target */
INVALID_PACKAGE_TARGET: "Invalid package target",
/** Package import not defined */
PACKAGE_IMPORT_NOT_DEFINED: "Package import '#import' is not defined"
};Usage Examples:
const resolve = require("enhanced-resolve").create({
exportsFields: ["exports"],
conditionNames: ["import", "require", "default"]
});
resolve(__dirname, "package/non-exported-path", (err, result) => {
if (err && err.message.includes("not defined by 'exports'")) {
console.log("Path not exported by package");
// Handle gracefully or try fallback resolution
}
});Helper functions for working with exports and imports fields.
/**
* Process exports field from package.json
* @param target - Target exports object
* @param field - Field value from package.json
* @param conditionNames - Condition names to match
* @param assertTarget - Assertion function for validation
*/
function processExportsField(
target: ExportsField,
field: any,
conditionNames: Set<string>,
assertTarget: (target: any) => void
): void;
/**
* Process imports field from package.json
* @param target - Target imports object
* @param field - Field value from package.json
* @param conditionNames - Condition names to match
* @param assertTarget - Assertion function for validation
*/
function processImportsField(
target: ImportsField,
field: any,
conditionNames: Set<string>,
assertTarget: (target: any) => void
): void;interface ExportsField {
[key: string]: string | ExportsConditions | false;
}
interface ExportsConditions {
[condition: string]: string | ExportsConditions | false;
}
interface ImportsField {
[key: string]: string | ImportsConditions | false;
}
interface ImportsConditions {
[condition: string]: string | ImportsConditions | false;
}
type ConditionNames = Set<string>;
interface PackageJsonWithModernFeatures {
name?: string;
version?: string;
main?: string;
module?: string;
browser?: string | { [key: string]: string | false };
exports?: ExportsField;
imports?: ImportsField;
type?: "module" | "commonjs";
}