【笔记】Tapable源码解析图以及webpack怎样实现一个插件plugin

Tapable源码解析图,如图所示:

 一个webpack plugin由一下几个步骤组成:

  1. 一个JavaScript类函数。
  2. 在函数原型 (prototype)中定义一个注入compiler对象的apply方法。
  3. apply函数中通过compiler插入指定的事件钩子,在钩子回调中拿到compilation对象
  4. 使用compilation操纵修改webapack内部实例数据。
  5. 异步插件,数据处理完后使用callback回调

开发webpack插件还需要了解其中两个核心的对象引用Compiler 和 Compilation,这里需要理解清楚他们的含义。

  • compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。
  • compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

实现一个如下需求的插件,针对某个打包生成的JS,对其内容的头部添加一个eslint语法检测的忽略说明,那样eslint就不会检测当前打包的js,如下代码:

class ignoreEslintPlugin {
  constructor(options) {
    this.options = options;
  }
  apply(compiler) {
    compiler.hooks.emit.tap('ignoreEslintPlugin', (compilation) => {
      var topInfo = '/* eslint-disable */\n';
      var content = topInfo + compilation.assets[this.options.filename].source();
      // console.info(chalk.green(content))
      compilation.assets[this.options.filename] = {
        source: () => content,
        size: () => content.length
      }
    })
  }
}

调用方式:

new ignoreEslintPlugin({filename: 'common.js'})

我们看下上面代码中的这个结构:

compiler.hooks.emit.tap('ignoreEslintPlugin', (compilation) => {
      
})

这一步主要是使用核心对象compiler的emit钩子,通过.tap方法注册到webpack中,在输出构建产物到dist目录之前执行。 在这里列出compiler对象的生命周期钩子
-> beforeRun 清除缓存
-> run 注册缓存数据钩子
-> beforeCompile
-> compile 开始编译
-> make 从入口分析依赖以及间接依赖模块,创建模块对象
-> buildModule 模块构建
-> normalModuleFactory 构建
-> seal 构建结果封装, 不可再更改
-> afterCompile 完成构建,缓存数据
-> emit 输出到dist目录

 参考地址:怎样编写一个简单的webpack插件

posted @ 2020-08-04 22:12  风雨后见彩虹  阅读(157)  评论(0编辑  收藏