webpack 插件是由「具有 apply 方法的 prototype 对象」所实例化出来的。这个 apply 方法在安装插件时,会被 webpack compiler 调用一次。apply 方法可以接收一个 webpack compiler 对象的引用,从而可以在回调函数中访问到 compiler 对象。一个webpack插件有以下特性

  1. 本质是一个构造函数
  2. 原型prototype实现了apply方法,可以通过参数注入compiler对象
  3. 可以在compiler的钩子里面获取compilation对象

compiler对象

compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。

compilation 对象

compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

由此可见,如果开发者需要通过一个插件的方式完成一个自定义的编译工作的话,如果涉及到需要改变编译后的资源产物,必定离不开这个 compilation 对象。

推荐使用 hooks 来实现的,旧版本是用 Tapable.plugin 

一个简单的插件定义

class FileListPlugin {
  apply(compiler) {

    compiler.hooks.compilation.tap('Compilation', compilation => {
      // 通过compiler的钩子获取compilation对象
      compilation.hooks.optimize.tap('CompilationOptimize', () => {
        console.log('优化资源')
      })
    })

    compiler.hooks.done.tap('file list plugin', stats => {
      console.log('done');
    })
  }
}

module.exports = exports = FileListPlugin

webpack引入插件

const FileListPlugin = require('./plugin/FIleListPlugin')
module.exports = {
  mode: 'development',
  entry: './src/index.js',
  plugins: [
    new FileListPlugin()
  ]
}