阿里云主机折上折
  • 微信号
Current Site:Index > Dependency collection and analysis process

Dependency collection and analysis process

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

Dependency Collection and Analysis Process

One of Webpack's core functionalities is the collection and analysis of module dependencies. This process determines the correctness and optimization level of the final bundled output. Dependency collection starts from the entry file and builds a complete dependency graph through both static analysis and dynamic resolution.

Static Dependency Analysis

Static analysis primarily handles explicitly declared dependencies in the code, such as ESM's import and CommonJS's require. Webpack parses these statements and extracts dependency paths:

// Example: Static dependencies
import utils from './utils.js';
const lodash = require('lodash');

The analysis process:

  1. Recognizes './utils.js' and 'lodash' as dependencies
  2. Resolves paths to absolute paths
  3. Creates reference relationships between modules

Special scenario handling:

  • Dynamic expressions trigger warnings
// Warning: Cannot be statically analyzed
const moduleName = 'utils';
require(`./${moduleName}`); 

Dynamic Dependency Handling

For scenarios that cannot be statically analyzed, Webpack provides specific syntax support:

// Explicitly declare possible paths
require.context('./components', false, /\.vue$/);

Processing flow:

  1. Scans files matching the regex in the specified directory
  2. Generates a virtual module mapping table
  3. Loads dynamically at runtime based on actual needs

Dependency Graph Construction

Collected dependencies form a directed graph data structure:

// Simplified dependency graph structure
{
  'entry.js': {
    deps: ['a.js', 'b.js'],
    exports: ['default']
  },
  'a.js': {
    deps: ['c.js'],
    exports: ['getName']
  }
}

Key properties include:

  • dependencies: List of direct dependencies
  • issuer: Information about the referrer
  • moduleGraph: Complete module relationship network

Circular Dependency Handling

Webpack resolves circular references through the following mechanisms:

// a.js
import { b } from './b';
export const a = 'A';

// b.js
import { a } from './a';
export const b = 'B';

Handling strategy:

  1. Marks the state of loaded modules
  2. Returns references that are not fully initialized
  3. Eventually forms a closed-loop reference relationship

Dependency Optimization Phase

Optimization operations performed after analysis:

  1. Tree Shaking:
// Marks unused exports
import { used, unused } from './module';
console.log(used);
  1. Scope Hoisting:
// Merges module scopes
// Original code
import { a } from './module';
console.log(a);

// Optimized
console.log('a');
  1. Dependency Grouping:
// Splits based on reference frequency
optimization.splitChunks: {
  chunks: 'all'
}

Custom Dependency Resolution

Modifies resolution logic through resolve configuration:

resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src')
  },
  extensions: ['.ts', '.js'],
  modules: ['node_modules', 'shared']
}

Advanced resolution example:

resolve.plugins: [
  new DirectoryNamedWebpackPlugin()
]

Dependency Analysis Tools

Analysis methods available during development:

  1. Stats Output:
webpack --profile --json > stats.json
  1. Visualization Tools:
new BundleAnalyzerPlugin({
  analyzerMode: 'static'
})
  1. Custom Reports:
compilation.hooks.finishModules.tap('DependencyReport', modules => {
  generateCustomReport(modules);
});

Performance Optimization Practices

Optimization examples in real projects:

// 1. Lazy loading
import('./heavyModule').then(module => {
  module.run();
});

// 2. Prefetching
import(/* webpackPrefetch: true */ './modal.js');

// 3. Shared dependencies
externals: {
  react: 'React'
}

Hook System for Dependency Collection

Extension points exposed by Webpack:

compiler.hooks.compilation.tap('DependencyTracking', (compilation) => {
  compilation.hooks.finishModules.tapAsync('AnalyzeDeps', (modules, callback) => {
    analyzeModuleGraph(modules);
    callback();
  });
});

Key Hook phases:

  • beforeResolve
  • afterResolve
  • After moduleGraph updates

Dependency Handling in Module Federation

Cross-application dependency sharing solution:

// app1/webpack.config.js
new ModuleFederationPlugin({
  name: 'app1',
  exposes: {
    './Button': './src/Button'
  }
});

// app2/webpack.config.js 
new ModuleFederationPlugin({
  name: 'app2',
  remotes: {
    app1: 'app1@http://localhost:3001/remoteEntry.js'
  }
});

Runtime dependency resolution flow:

  1. Loads remote entry files
  2. Establishes version mapping tables
  3. Loads remote modules on demand

Caching and Incremental Analysis

Persistent cache configuration example:

cache: {
  type: 'filesystem',
  buildDependencies: {
    config: [__filename]
  }
}

Cache invalidation scenarios:

  • File content changes
  • Loader configuration modifications
  • Resolution rule changes

Dependency Version Conflict Resolution

Common solutions:

  1. Version Negotiation:
resolve: {
  alias: {
    'react': path.resolve('./node_modules/react')
  }
}
  1. Dependency Hoisting:
optimization: {
  runtimeChunk: 'single'
}
  1. Externalization:
externals: {
  'lodash': '_'
}

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

如果侵犯了你的权益请来信告知我们删除。邮箱: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 ☕.