webpack系列学习十二(如何编写一个plugin)

130 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

自定义plugin的实现

插件就是在某个时刻,帮助我们完善一些工作的机制。它的复杂程度比loader高,场景比loader广,因为他作用于整个webpack打包生命周期的。webpack打包编译过程中,会触发一系列的钩子事件(插件)

插件基本结构

// 插件的结构  类

//  必须要用apply函数

class TxtWebpackPlugin {
  constructor(options) {
    console.log(options);
  }
  // 提供当前打包的compiler对象,可以拿到钩子,注册事件
  apply(compiler) {
    // compiler.hooks
    compiler.hooks.emit.tapAsync("TxtWebpackPlugin", (compilation, cb) => {
      // console.log(compilation.assets)
      // 往资源模块中添加一个资源
      // emit AsyncSeriesHook  在⽣成⽂件到output⽬录之前执⾏,回调参数:compilation
      const content = `这是一个测试的资源模块`
      compilation.assets["frllk.txt"] = {
        source: function () {
          return content
        },
        size: function () {
          return content.length // 打包信息栏的显示信息,并不影响文件的真实体积,需要保持文档的准确性
        }
      }
      cb()
    })
  }   
}
 
module.exports = TxtWebpackPlugin

基本流程

Webpack 的基本流程可以分为 3 个阶段:

  • 准备阶段:主要任务是创建 CompilerCompilation 对象;
  • 编译阶段:这个阶段任务是完成 modules 解析,并且⽣成 chunks;
  • module 解析:包含了三个主要步骤,创建实例、 loaders 应⽤和依赖收集;
  • chunks ⽣成,主要步骤是找到每个 chunk 所需要包含的 modules
  • 产出阶段:这个阶段的主要任务是根据 chunks ⽣成最终⽂件,主要有三个步骤:模板 Hash 更新,模板渲染 chunk,⽣成⽂件。

Compiler

Compiler 模块是 Webpack 最核⼼的模块。每次执⾏ Webpack 构建的时候,在 Webpack 内部,会⾸ 先实例化⼀个 Compiler 对象,然后调⽤它的 run ⽅法来开始⼀次完整的编译过程。我们直接使⽤ Webpack API webpack(options) 的⽅式得到的就是⼀个 Compiler 实例化的对象,这时候 Webpack 并不会⽴即开始构建,需要我们⼿动执⾏ comipler.run() 才可以。

Compiler 钩⼦

可以通过下⾯的代码,获取了对应的钩⼦名称:

const webpack = require("webpack") // 引入webpack
const config = require("./webpack.config") // 引入webpack打包配置

const compiler = webpack(config) // 执行webpack,把配置传进去,生成一个对象compiler,里面记录了本次打包的所有信息

// compiler.hooks()
Object.keys(compiler.hooks).forEach(hookName => {
  // 同步钩子 用tap
  // 异步钩子  用tapAsync
  compiler.hooks[hookName].tap("事件名称", () => {
    console.log('%c%s', 'color: red; background: yellow; font-size: 16px;', 'run---------->', hookName)
  })
})

compiler.run() // 入口函数

得到 compiler.run() 之后的⼯作流程:

image.png