初识Webpack(三)

313 阅读3分钟

插件plugin

插件webpack 除了loader以外的另一个核心功能。而通过对Webpack源码的观察,我们发现Webpack自身也是构建于各类插件之上。

插件目的在于解决上一篇文章所介绍的loader 无法实现的事。通过上篇文章的介绍,我们知道了loader的主要作用是对各类的文件的解析、预处理。但如果仅有这些对于我们的日常开发是远远不够的,这也是插件所补充的部分。

如何使用插件

我们日常开发中如果需要使用Webpack插件,就需要在webpack.config.js中进行配置,比如:

const HtmlWebpackPlugin = require('html-webpack-plugin'); 
const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /.(js|jsx)$/,
        use: 'babel-loader',
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
  ],
};

上面的例子中首先通过require加载通过npm安装的插件,接着在module.exports中的plugins中传入我们所需要的插件的实例,这里通过new来创建一个插件的实例并进行加载。这里的例子是一个解析html的插件,插件需要传入一个参数是需要处理的html的相对路径,然后插件内部对该html进行解析,构建。该插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的 bundle。HtmlWebpackPlugin简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。

一个插件是如何开发的

plugins是可以用自身原型方法apply来实例化的对象。apply只在安装插件被Webpack compiler执行一次。apply方法传入一个webpck compiler的引用,来访问编译器回调。一个简单的插件代码结构是这样:

class Plugin {
  constructor(options) {}
  apply(compiler) {
    //...
  }
}

module.exports = Plugin

这里以HtmlWebpackPlugin的代码为例:

apply(compiler){
    compiler.hooks.make.tapAsync(
         //...
    )
}

这里的compiller.hooks.make()函数,这是一个异步并发 AsyncParallelBailHook 钩子,也就是在编译完成之前执行的钩子函数,compiler里有很多钩子函数是在webpackcompile编译过程的不同阶段进行操作的钩子,这样也就扩展了我们的webpack的功能。

插件的执行过程

首先介绍一下CompilerCompiler 模块是 webpack 的核心引擎,它通过 CLI 或 Node API 传递的所有选项,创建出一个 compilation 实例。它扩展(extend)自 Tapable 类,以便于我们注册和调用插件。大多数面向用户的插件首先在 Compiler 上注册。

监听

Compiler 支持可以监控文件系统的监听(watching)机制,并且在文件修改时重新编译。当处于监听模式(watch mode)时,compiler 会触发诸如 watchRunwatchClose 和 invalid 等额外的事件。通常用于开发环境中使用,也常常会在 webpack-dev-server 这些工具的底层之下调用,由此开发人员无须每次都使用手动方式重新编译。还可以通过 CLI 进入监听模式。

执行过程
  1. Webpack开始读取插件配置的过程中会先执行 new xxxPlugin(options) 初始化一个 xxxxPlugin插件来获得其实例。
  2. 在初始化 compiler 对象后调用 xxxxPlugin.apply(compiler) 给插件实例传入 compiler 对象。
  3. 插件实例在获取到 compiler 对象后,就可以通过compiler.plugin(事件名称, 回调函数) 监听到 Webpack广播出来的事件。然后根据不同的事件,进行不同的操作。并且可以通过 compiler 对象去操作 Webpack

几个强烈推荐学习的插件源码