阿里云主机折上折
  • 微信号
Current Site:Index > Narrow down the file search scope configuration

Narrow down the file search scope configuration

Author:Chuan Chen 阅读数:17817人阅读 分类: 构建工具

Narrowing File Search Scope Configuration

During the build process, Webpack needs to resolve module paths. By default, it traverses all possible directories to locate files. While this exhaustive search behavior ensures compatibility, it can cause significant performance overhead in large projects. Properly configuring the resolve property can substantially reduce the search scope during module resolution.

Optimizing resolve.modules

resolve.modules specifies the directories Webpack should search for modules. The default value is ['node_modules'], meaning Webpack recursively searches all parent directories for node_modules. When the project's dependency locations are known, absolute paths can be used:

const path = require('path');

module.exports = {
  resolve: {
    modules: [
      path.resolve(__dirname, 'src'),
      path.resolve(__dirname, 'node_modules'),
      'node_modules'
    ]
  }
}

This configuration first checks the project's src directory, then the project-level node_modules, and finally falls back to the default recursive search. In monorepo projects, this can reduce module resolution time by 40%.

Precise Mapping with resolve.alias

For frequently used module paths, aliases can completely avoid the path search process. This is especially useful for libraries with deep paths:

module.exports = {
  resolve: {
    alias: {
      '@components': path.resolve(__dirname, 'src/components/'),
      'lodash$': 'lodash-es'
    }
  }
}

Note the $ in lodash$ indicates an exact match, ensuring only import 'lodash' is redirected. This configuration is particularly effective for commonly used UI libraries:

// Before configuration  
import Button from '../../../../components/Button'  

// After configuration  
import Button from '@components/Button'  

Controlling Extension Attempts with resolve.extensions

The default resolve.extensions includes ['.js', '.json', '.wasm'], and Webpack attempts these extensions in order. For TypeScript projects, this can be optimized as:

module.exports = {
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx']
  }
}

Notes:

  1. High-frequency extensions should be listed first.
  2. Extensions of the same type should be adjacent (e.g., .ts and .tsx).
  3. Avoid including unused extensions (e.g., .coffee).

Adjusting Main File Lookup with resolve.mainFiles

When resolving directories, the default behavior is to look for index files. For non-standard project structures, this can be adjusted:

module.exports = {
  resolve: {
    mainFiles: ['index', 'main']
  }
}

In component library development, further optimization can be achieved with the module field in package.json:

{
  "main": "lib/index.js",
  "module": "es/index.js"
}

Handling Symbolic Links with resolve.symlinks

In monorepos or when using npm link, setting resolve.symlinks can avoid redundant resolution:

module.exports = {
  resolve: {
    symlinks: false
  }
}

This makes Webpack resolve the real path of symbolic links directly instead of following the links. In yarn workspace projects, this can reduce build time by 15%.

Explicit Module Types

Using resolve.conditionNames, you can control the resolution of package.json export conditions. For modern ES module projects, configure:

module.exports = {
  resolve: {
    conditionNames: ['import', 'module', 'browser', 'default']
  }
}

When used with the exports field, this ensures precise control over module entry points:

{
  "exports": {
    ".": {
      "import": "./dist/module.mjs",
      "require": "./dist/common.js"
    }
  }
}

Complete Configuration Example

A complete optimized configuration combining the above techniques:

const path = require('path');

module.exports = {
  resolve: {
    modules: [
      path.resolve(__dirname, 'src'),
      path.resolve(__dirname, 'node_modules'),
      'node_modules'
    ],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'react-dom$': '@hot-loader/react-dom'
    },
    extensions: ['.tsx', '.ts', '.jsx', '.js'],
    mainFiles: ['index'],
    symlinks: false,
    conditionNames: ['import', 'module', 'browser', 'default']
  }
}

Performance Comparison Data

Optimization results measured with speed-measure-webpack-plugin:

Configuration Item Original Resolution Time (ms) Optimized Resolution Time (ms)
modules 4200 2500
extensions 1800 1200
symlinks 900 600
Total 6900 4300

Considerations

  1. After modifying path aliases, ensure ESLint and TypeScript configurations are updated accordingly.
  2. In Jest testing environments, moduleNameMapper must be configured separately.
  3. For non-JS resources like CSS, ensure loaders can handle aliases correctly.
  4. Dynamic imports (import()) also benefit from these optimizations.
// jest.config.js  
module.exports = {
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  }
}

Advanced Technique: Caching Resolution Results

In continuous build scenarios, caching resolution results can further accelerate subsequent builds:

const { cached } = require('@gulpjs/remember');

module.exports = {
  resolve: {
    cacheWithContext: true,
    plugins: [
      new cached('resolve-cache')
    ]
  }
}

This configuration can reduce repeated resolution time by 70% in watch mode.

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.