Oxc Resolver
Oxc Resolver is a high-performance, Rust-ported module resolver designed for Node.js environments, mimicking the behavior of `enhanced-resolve`, `tsconfig-paths-webpack-plugin`, and `tsconfck`. It provides a comprehensive implementation of both ESM and CommonJS module resolution algorithms as specified by Node.js. Currently stable at version 11.19.1, it receives frequent updates with minor version bumps and bug fixes, indicating active development. Key features include built-in support for TypeScript's `tsconfig.json` paths, project references, and automatic `tsconfig` discovery, making it a robust alternative for bundlers, linters, and language servers. It boasts significant performance improvements, such as being 28x faster than `webpack/enhanced-resolve`, and supports an in-memory file system and `tracing` instrumentation, distinguishing it from purely JavaScript-based resolvers.
Common errors
-
Error: Package subpath '. ' is not defined by "exports" in
cause Attempting to resolve a package's subpath or main entry point via the `exports` field without matching `conditionNames`.fixConfigure `ResolveOptions` with `conditionNames: ['node', 'require']` (for CommonJS) or `['node', 'import']` (for ESM) to match the expected resolution conditions for the `exports` field. This tells the resolver which export conditions to consider. -
Error: Module not found: Can't resolve 'your-module'
cause The module specifier does not resolve to a file or directory based on current options, potentially due to incorrect paths, missing extensions, or unrecognized aliases.fixVerify the module path, ensuring all segments are correct. Check `ResolveOptions` for `extensions`, `alias`, `modules`, `mainFields`, and `mainFiles`. If using TypeScript `paths`, ensure you are using `resolveFileSync` or `resolveFileAsync` to trigger `tsconfig.json` discovery. -
Error: Cannot find module 'oxc-resolver' or 'oxc-resolver/index.js' (when using require())
cause Attempting to `require('oxc-resolver')` in a pure ESM context, or if the package is published as ESM-only.fixEnsure your project is configured for ESM (e.g., `"type": "module"` in `package.json` or `.mjs` extension) and use `import { ... } from 'oxc-resolver';`. If you must use CommonJS, ensure your Node.js version supports ESM interop for CJS, or check if the library provides a CJS entry point.
Warnings
- breaking The behavior of `NODE_PATH` environment variable resolution was implicitly enabled in versions prior to 11.19.0. In `v11.19.0`, a new `node_path` option was introduced to explicitly control this behavior, which can disable it. This might alter resolution if you were relying on implicit `NODE_PATH` handling.
- gotcha There are distinct differences between `resolver.sync(directory, specifier)` and `resolver.resolveFileSync(file, specifier)`. The `sync` method takes a directory path and relies on manually configured `tsconfig` options. In contrast, `resolveFileSync` takes a file path and automatically discovers the relevant `tsconfig.json` by traversing parent directories, which is crucial for respecting `paths` aliases and project references based on the file's context.
- gotcha When resolving packages that utilize the `exports` field in their `package.json`, particularly in CommonJS contexts or when explicit `conditionNames` are not provided, you might encounter 'Package subpath '.' is not defined by "exports"' errors. This occurs because the `exports` field requires specific conditions to match the resolution context (e.g., 'node', 'require', 'import').
- gotcha Yarn Plug'n'Play (PnP) support requires specific conditions to work correctly, including the program being called via a `yarn` command (setting `process.versions.pnp`) and the presence of a `.pnp.cjs` manifest file in a parent directory. Improper setup can lead to module not found errors.
Install
-
npm install oxc-resolver -
yarn add oxc-resolver -
pnpm add oxc-resolver
Imports
- resolveSync
const { resolveSync } = require('oxc-resolver')import { resolveSync } from 'oxc-resolver' - ResolverFactory
const ResolverFactory = require('oxc-resolver').ResolverFactoryimport { ResolverFactory } from 'oxc-resolver' - ResolveOptions, ResolveResult
import type { ResolveOptions, ResolveResult } from 'oxc-resolver'
Quickstart
import { ResolverFactory, resolveSync } from 'oxc-resolver';
import * as path from 'path';
import * as fs from 'fs';
async function runResolutionExample() {
const tempDir = path.join(process.cwd(), 'temp_oxc_resolver_test');
// Setup: Create a temporary directory structure and tsconfig.json
fs.mkdirSync(path.join(tempDir, 'src', 'app'), { recursive: true });
fs.writeFileSync(
path.join(tempDir, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
baseUrl: '.',
paths: {
'@app/*': ['src/app/*'],
},
},
}, null, 2)
);
fs.writeFileSync(path.join(tempDir, 'src', 'app', 'moduleA.ts'), 'export const a = 1;');
// 1. Basic synchronous resolution (directory-based context)
const simpleResolvedPath = resolveSync(tempDir, './src/app/moduleA.ts');
console.log('Simple resolved path (sync):', simpleResolvedPath?.path);
// 2. Advanced resolution using ResolverFactory with file-based context and TSConfig discovery
const resolver = new ResolverFactory();
const sourceFilePath = path.join(tempDir, 'src', 'main.ts');
fs.writeFileSync(sourceFilePath, 'import { a } from "@app/moduleA";'); // Dummy file for context
const fileBasedResolvedPath = await resolver.resolveFileAsync(sourceFilePath, '@app/moduleA');
console.log('File-based resolved path (async with tsconfig):', fileBasedResolvedPath?.path);
// Cleanup
fs.unlinkSync(path.join(tempDir, 'src', 'app', 'moduleA.ts'));
fs.unlinkSync(path.join(tempDir, 'tsconfig.json'));
fs.unlinkSync(sourceFilePath);
fs.rmdirSync(path.join(tempDir, 'src', 'app'));
fs.rmdirSync(path.join(tempDir, 'src'));
fs.rmdirSync(tempDir);
}
runResolutionExample().catch(console.error);