webpack编译过程中的几个生命钩子周期

207 阅读1分钟

以下是Webpack核心生命周期钩子的详细解析及示例说明:

一、初始化阶段

  1. ‌**entryOption**‌
    处理entry配置验证,可修改入口配置

    compiler.hooks.entryOption.tap('MyPlugin', (context, entry) => {
      return { main: './new-entry.js' }; // 动态修改入口
    });
    
  2. ‌**afterPlugins**‌
    所有插件注册完成后触发,适合初始化全局变量

    compiler.hooks.afterPlugins.tap('MyPlugin', () => {
      global.__DEV__ = process.env.NODE_ENV === 'development';
    });
    

二、编译阶段

  1. ‌**compile**‌
    开始编译前触发,可注入自定义参数8

    compiler.hooks.compile.tap('MyPlugin', (params) => {
      params.compilationDependencies.add('custom-dep');
    });
    
  2. ‌**compilation**‌
    创建compilation对象时触发,常用于修改模块处理逻辑

    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      compilation.hooks.optimize.tap('MyPlugin', () => {
        // 模块优化逻辑
      });
    });
    

三、模块处理阶段

  1. ‌**make**‌
    分析模块依赖图的起点,可拦截模块解析

    compiler.hooks.make.tapAsync('MyPlugin', (compilation, callback) => {
      compilation.addEntry(__dirname, 'custom-module.js', callback);
    });
    
  2. ‌**afterCompile**‌
    模块编译完成后触发,适合收集编译元数据

    compiler.hooks.afterCompile.tap('MyPlugin', (compilation) => {
      console.log(compilation.fileDependencies);
    });
    

四、输出阶段

  1. ‌**emit**‌
    生成资源到output目录前触发,可修改最终输出

    compiler.hooks.emit.tap('MyPlugin', (compilation) => {
      compilation.assets['license.txt'] = {
        source: () => 'MIT License',
        size: () => 10
      };
    });
    
  2. ‌**afterEmit**‌
    资源已写入磁盘后触发,适合执行清理操作

    compiler.hooks.afterEmit.tapPromise('MyPlugin', async () => {
      await fs.promises.unlink('temp-file.js');
    });
    
  3. ‌**done**‌
    整个构建流程结束时触发,用于统计构建信息

    compiler.hooks.done.tap('MyPlugin', (stats) => {
      console.log(`构建耗时:${stats.toJson().time}ms`);
    });
    

典型应用场景

  • 性能监控‌:通过done钩子统计构建时间
  • 动态入口‌:利用entryOption实现多页面自动配置
  • 资源注入‌:在emit阶段添加LICENSE文件