> ## Documentation Index
> Fetch the complete documentation index at: https://docs.webpack.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Resolver API

> webpack Resolver API - module resolution and ResolverFactory

The Resolver API provides webpack's module resolution functionality, allowing you to resolve module paths programmatically and customize the resolution process.

## ResolverFactory

The ResolverFactory is responsible for creating and caching resolver instances.

### Accessing ResolverFactory

The ResolverFactory is available on the Compiler instance:

```javascript theme={null}
class MyPlugin {
  apply(compiler) {
    const resolverFactory = compiler.resolverFactory;
    
    // Create or get a resolver
    const resolver = resolverFactory.get('normal');
  }
}
```

### get()

Returns a resolver for the specified type.

```typescript theme={null}
resolverFactory.get(
  type: string,
  resolveOptions?: ResolveOptions
): Resolver
```

<ParamField path="type" type="string" required>
  Type of resolver to get. Common types:

  * `'normal'` - Standard module resolution
  * `'loader'` - Loader resolution
  * `'context'` - Context module resolution
</ParamField>

<ParamField path="resolveOptions" type="ResolveOptions">
  Optional resolve configuration options.
</ParamField>

<ResponseField name="return" type="Resolver">
  Resolver instance with `resolve()` method and other utilities.
</ResponseField>

**Example:**

```javascript theme={null}
const resolver = compiler.resolverFactory.get('normal', {
  extensions: ['.js', '.json', '.ts'],
  alias: {
    '@': path.resolve(__dirname, 'src')
  }
});
```

## Resolver

A Resolver instance provides methods for resolving module paths.

### resolve()

Resolves a module path.

```typescript theme={null}
resolver.resolve(
  context: object,
  path: string,
  request: string,
  resolveContext: object,
  callback: (err: Error | null, result?: string, details?: object) => void
): void
```

<ParamField path="context" type="object" required>
  Context object (usually an empty object `{}`).
</ParamField>

<ParamField path="path" type="string" required>
  The directory from which to resolve.
</ParamField>

<ParamField path="request" type="string" required>
  The module request to resolve (e.g., 'lodash', './utils', '@/components').
</ParamField>

<ParamField path="resolveContext" type="object" required>
  Resolve context object (usually an empty object `{}`).
</ParamField>

<ParamField path="callback" type="function" required>
  Callback invoked when resolution completes.

  **Parameters:**

  * `err` - Error if resolution failed, null otherwise
  * `result` - Resolved absolute path
  * `details` - Additional resolution details
</ParamField>

**Example:**

```javascript theme={null}
const resolver = compiler.resolverFactory.get('normal');

resolver.resolve(
  {},
  process.cwd(),
  'lodash',
  {},
  (err, result) => {
    if (err) {
      console.error('Failed to resolve:', err);
      return;
    }
    console.log('Resolved to:', result);
    // Output: /path/to/project/node_modules/lodash/lodash.js
  }
);
```

### withOptions()

Creates a new resolver with modified options.

```typescript theme={null}
resolver.withOptions(
  options: Partial<ResolveOptions>
): Resolver
```

<ParamField path="options" type="ResolveOptions" required>
  Options to override or add to the existing resolver configuration.
</ParamField>

<ResponseField name="return" type="Resolver">
  New resolver instance with merged options.
</ResponseField>

**Example:**

```javascript theme={null}
const baseResolver = compiler.resolverFactory.get('normal');

const tsResolver = baseResolver.withOptions({
  extensions: ['.ts', '.tsx', '.js', '.jsx']
});

tsResolver.resolve({}, process.cwd(), './App', {}, (err, result) => {
  console.log('Resolved TypeScript module:', result);
});
```

## Resolve Options

Configuration options for customizing resolver behavior.

### Common Options

```javascript theme={null}
const resolveOptions = {
  // File extensions to try
  extensions: ['.js', '.json', '.jsx', '.ts', '.tsx'],
  
  // Main fields to try when resolving packages
  mainFields: ['browser', 'module', 'main'],
  
  // Main files to try when resolving directories
  mainFiles: ['index'],
  
  // Module directories to search
  modules: ['node_modules'],
  
  // Alias configuration
  alias: {
    '@': path.resolve(__dirname, 'src'),
    'components': path.resolve(__dirname, 'src/components'),
    'utils$': path.resolve(__dirname, 'src/utils/index.js')
  },
  
  // Fallback options when resolution fails
  fallback: {
    'crypto': require.resolve('crypto-browserify'),
    'stream': require.resolve('stream-browserify')
  },
  
  // Symlink options
  symlinks: true,
  
  // Cache resolution results
  unsafeCache: true,
  
  // Resolve to context
  resolveToContext: false,
  
  // Enforce certain file extensions
  enforceExtension: false,
  
  // Description files (package.json)
  descriptionFiles: ['package.json'],
  
  // Custom conditions
  conditionNames: ['webpack', 'production', 'development']
};

const resolver = compiler.resolverFactory.get('normal', resolveOptions);
```

## Hooking into Resolution

The ResolverFactory provides hooks to customize the resolution process.

### resolveOptions Hook

Called before a resolver is created, allowing you to modify resolve options.

```javascript theme={null}
compiler.resolverFactory.hooks.resolveOptions
  .for('normal')
  .tap('MyPlugin', (resolveOptions) => {
    // Modify resolve options
    return {
      ...resolveOptions,
      extensions: [...resolveOptions.extensions, '.custom']
    };
  });
```

### resolver Hook

Called after a resolver is created, allowing you to add plugins to it.

```javascript theme={null}
compiler.resolverFactory.hooks.resolver
  .for('normal')
  .tap('MyPlugin', (resolver, resolveOptions, userResolveOptions) => {
    // Add custom plugin to resolver
    resolver.hooks.result.tap('MyPlugin', (result) => {
      console.log('Resolved:', result);
      return result;
    });
  });
```

## Practical Examples

### Custom Module Resolution Plugin

```javascript theme={null}
class CustomResolverPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap(
      'CustomResolverPlugin',
      (compilation, { normalModuleFactory }) => {
        normalModuleFactory.hooks.beforeResolve.tapAsync(
          'CustomResolverPlugin',
          (resolveData, callback) => {
            const resolver = compiler.resolverFactory.get('normal');
            
            // Custom resolution logic
            if (resolveData.request.startsWith('custom:')) {
              const customPath = resolveData.request.replace('custom:', './custom/');
              
              resolver.resolve(
                {},
                resolveData.context,
                customPath,
                {},
                (err, result) => {
                  if (err) return callback(err);
                  
                  resolveData.request = result;
                  callback();
                }
              );
            } else {
              callback();
            }
          }
        );
      }
    );
  }
}

module.exports = CustomResolverPlugin;
```

### Aliasing Plugin

```javascript theme={null}
class AliasPlugin {
  constructor(aliases) {
    this.aliases = aliases;
  }
  
  apply(compiler) {
    compiler.resolverFactory.hooks.resolveOptions
      .for('normal')
      .tap('AliasPlugin', (resolveOptions) => {
        return {
          ...resolveOptions,
          alias: {
            ...resolveOptions.alias,
            ...this.aliases
          }
        };
      });
  }
}

module.exports = AliasPlugin;
```

**Usage:**

```javascript theme={null}
const AliasPlugin = require('./AliasPlugin');

module.exports = {
  // ...
  plugins: [
    new AliasPlugin({
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils'),
      '@api': path.resolve(__dirname, 'src/api')
    })
  ]
};
```

### Resolution Logger Plugin

```javascript theme={null}
class ResolutionLoggerPlugin {
  apply(compiler) {
    compiler.resolverFactory.hooks.resolver
      .for('normal')
      .tap('ResolutionLoggerPlugin', (resolver) => {
        resolver.hooks.result.tap('ResolutionLoggerPlugin', (result) => {
          console.log('Resolved:', {
            path: result.path,
            request: result.request,
            context: result.context
          });
        });
      });
  }
}

module.exports = ResolutionLoggerPlugin;
```

### Conditional Resolution Plugin

```javascript theme={null}
class ConditionalResolvePlugin {
  apply(compiler) {
    const isDevelopment = compiler.options.mode === 'development';
    
    compiler.resolverFactory.hooks.resolveOptions
      .for('normal')
      .tap('ConditionalResolvePlugin', (resolveOptions) => {
        return {
          ...resolveOptions,
          alias: {
            ...resolveOptions.alias,
            // Use mock API in development
            './api': isDevelopment 
              ? './api.mock.js' 
              : './api.prod.js'
          }
        };
      });
  }
}

module.exports = ConditionalResolvePlugin;
```

## Using Resolver Programmatically

```javascript theme={null}
const webpack = require('webpack');
const path = require('path');

// Create a simple compiler to get resolver
const compiler = webpack({
  mode: 'development',
  entry: './src/index.js'
});

// Get resolver
const resolver = compiler.resolverFactory.get('normal');

// Resolve multiple modules
const modulesToResolve = [
  'react',
  'lodash',
  './utils/helpers',
  '@/components/App'
];

modulesToResolve.forEach(request => {
  resolver.resolve(
    {},
    process.cwd(),
    request,
    {},
    (err, result) => {
      if (err) {
        console.error(`Failed to resolve ${request}:`, err.message);
      } else {
        console.log(`${request} → ${result}`);
      }
    }
  );
});
```

## Advanced: Custom Resolver Plugin

Create a completely custom resolver for special file types:

```javascript theme={null}
class VirtualModuleResolverPlugin {
  constructor(virtualModules) {
    this.virtualModules = virtualModules;
  }
  
  apply(compiler) {
    compiler.hooks.compilation.tap(
      'VirtualModuleResolverPlugin',
      (compilation, { normalModuleFactory }) => {
        normalModuleFactory.hooks.beforeResolve.tap(
          'VirtualModuleResolverPlugin',
          (resolveData) => {
            const request = resolveData.request;
            
            if (this.virtualModules[request]) {
              // Provide virtual module content
              resolveData.request = `virtual-module://${request}`;
            }
            
            return resolveData;
          }
        );
        
        normalModuleFactory.hooks.afterResolve.tap(
          'VirtualModuleResolverPlugin',
          (resolveData) => {
            if (resolveData.request.startsWith('virtual-module://')) {
              const moduleName = resolveData.request.replace('virtual-module://', '');
              resolveData.createData.resource = resolveData.request;
              resolveData.createData.loaders = [];
            }
            
            return resolveData;
          }
        );
      }
    );
  }
}

module.exports = VirtualModuleResolverPlugin;
```

**Usage:**

```javascript theme={null}
module.exports = {
  // ...
  plugins: [
    new VirtualModuleResolverPlugin({
      'config': `module.exports = { apiUrl: 'https://api.example.com' };`,
      'version': `module.exports = '1.0.0';`
    })
  ]
};
```

## See Also

* [Compiler API](/api/compiler) - Compiler instance methods
* [Resolve Configuration](https://webpack.js.org/configuration/resolve/) - Configuration options
* [Module Resolution](https://webpack.js.org/concepts/module-resolution/) - How webpack resolves modules
