Webpack自定义插件中的compiler对象

183 阅读3分钟

在 Webpack 插件开发中,apply 方法是一个关键部分。它是 Webpack 插件的入口点,Webpack 会在初始化时调用每个插件的 apply 方法,并传入一个 compiler 对象。compiler 对象是 Webpack 的核心实例,它包含了 Webpack 的完整配置、构建流程以及各种生命周期钩子(Hooks)。

compiler 对象的作用

compiler 对象是 Webpack 的核心实例,负责整个构建过程的调度和管理。通过 compiler,你可以访问 Webpack 的配置、注册钩子、监听构建事件,并在适当的时机执行自定义逻辑。

compiler 的主要属性和方法

1. compiler.options

  • 这是 Webpack 的完整配置对象,包含了你在 webpack.config.js 中定义的所有配置项。
  • 你可以通过 compiler.options 访问或修改 Webpack 的配置。

javascript

复制

apply(compiler) {
  console.log(compiler.options); // 输出 Webpack 配置
}

2. compiler.hooks

  • compiler.hooks 是 Webpack 提供的生命周期钩子集合。通过它,你可以在构建过程的不同阶段插入自定义逻辑。
  • 每个钩子都是一个 Tapable 实例,支持通过 .tap 方法注册回调函数。

常用钩子:

  • entryOption: 在 Webpack 处理入口配置时触发。
  • beforeRun: 在 Webpack 开始执行构建之前触发。
  • run: 在 Webpack 开始构建时触发。
  • compile: 在 Webpack 开始编译之前触发。
  • emit: 在生成资源并输出到目录之前触发。
  • done: 在构建完成后触发。

示例:

javascript

复制

apply(compiler) {
  compiler.hooks.beforeRun.tap('MyPlugin', () => {
    console.log('Webpack is about to start building...');
  });

  compiler.hooks.done.tap('MyPlugin', (stats) => {
    console.log('Build completed!');
  });
}

3. compiler.inputFileSystem 和 compiler.outputFileSystem

  • 这两个属性是 Webpack 使用的文件系统实例,分别用于读取输入文件和写入输出文件。
  • 默认情况下,Webpack 使用 Node.js 的 fs 模块,但你也可以替换为自定义的文件系统(比如内存文件系统)。

示例:

javascript

复制

apply(compiler) {
  const inputFileSystem = compiler.inputFileSystem;
  const outputFileSystem = compiler.outputFileSystem;

  // 读取文件
  inputFileSystem.readFile('path/to/file', (err, data) => {
    if (err) throw err;
    console.log(data.toString());
  });

  // 写入文件
  outputFileSystem.writeFile('path/to/output', 'Hello World', (err) => {
    if (err) throw err;
    console.log('File written!');
  });
}

4. compiler.context

  • 这是 Webpack 的上下文路径,通常是项目的根目录。
  • 你可以通过 compiler.context 获取项目的根目录路径。

示例:

javascript

复制

apply(compiler) {
  console.log('Project root:', compiler.context);
}

5. compiler.webpack

  • 这是 Webpack 的 API 对象,包含了 Webpack 的核心功能和方法。
  • 你可以通过它访问 Webpack 的内部模块或工具函数。

示例:

javascript

复制

apply(compiler) {
  const { sources } = compiler.webpack;
  console.log(sources); // 输出 Webpack 的 sources 模块
}

6. compiler.run 和 compiler.watch

  • compiler.run 用于启动一次构建。
  • compiler.watch 用于启动监听模式,当文件变化时自动重新构建。

示例:

javascript

复制

apply(compiler) {
  // 手动启动构建
  compiler.run((err, stats) => {
    if (err) throw err;
    console.log('Build completed!');
  });

  // 启动监听模式
  compiler.watch({}, (err, stats) => {
    if (err) throw err;
    console.log('Rebuild completed!');
  });
}

compiler 的生命周期钩子(Hooks)

Webpack 的构建过程分为多个阶段,每个阶段都有对应的钩子。以下是一些常用的钩子及其触发时机:

钩子名称触发时机
entryOption在处理入口配置时触发。
beforeRun在 Webpack 开始执行构建之前触发。
run在 Webpack 开始构建时触发。
compile在 Webpack 开始编译之前触发。
thisCompilation在创建新的 compilation 对象时触发。
compilation在 compilation 对象创建完成后触发。
emit在生成资源并输出到目录之前触发。
afterEmit在资源输出到目录之后触发。
done在构建完成后触发。
failed在构建失败时触发。

示例:监听 emit 钩子

emit 钩子是一个常用的钩子,它在 Webpack 生成资源并输出到目录之前触发。你可以在这个阶段修改输出内容。

javascript

复制

class EmitPlugin {
  apply(compiler) {
    compiler.hooks.emit.tap('EmitPlugin', (compilation) => {
      // 遍历所有生成的文件
      for (const file of Object.keys(compilation.assets)) {
        console.log(`Generated file: ${file}`);
      }

      // 添加一个自定义文件
      compilation.assets['custom-file.txt'] = {
        source: () => 'This is a custom file!',
        size: () => 21,
      };
    });
  }
}

module.exports = EmitPlugin;

总结

  • compiler 是 Webpack 的核心实例,包含了 Webpack 的配置、构建流程和生命周期钩子。
  • 通过 compiler.hooks,你可以在构建过程的不同阶段插入自定义逻辑。
  • compiler 还提供了文件系统、上下文路径等实用工具,方便你扩展 Webpack 的功能。