6-3 如何编写一个 plugin

2020-06-01  本文已影响0人  love丁酥酥

1. 简介

插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中。插件能够 钩入(hook) 到在每个编译(compilation)中触发的所有关键事件。在编译的每一步,插件都具备完全访问 compiler 对象的能力,如果情况合适,还可以访问当前 compilation 对象。

创建插件比创建 loader 更加高级,因为你将需要理解一些 webpack 底层的内部特性来做相应的钩子。

2. 创建插件

webpack 插件由以下组成:

// A JavaScript class.
class MyExampleWebpackPlugin {
  // Define `apply` as its prototype method which is supplied with compiler as its argument
  apply(compiler) {
    // Specify the event hook to attach to
    compiler.hooks.emit.tapAsync(
      'MyExampleWebpackPlugin',
      (compilation, callback) => {
        console.log('This is an example plugin!');
        console.log('Here’s the `compilation` object which represents a single build of assets:', compilation);

        // Manipulate the build using the plugin API provided by webpack
        compilation.addModule(/* ... */);

        callback();
      }
    );
  }
}

3. 基础的 plugin 结构

插件是在其原型上拥有 apply 方法的实例化对象。在安装插件时,webpack编译器会调用这个apply方法一次。apply方法有一个对底层webpack编译器的引用,它授予对编译器回调的访问权。一个简单的插件结构如下:

class HelloWorldPlugin {
  apply(compiler) {
    compiler.hooks.done.tap('Hello World Plugin', (
      stats /* stats is passed as an argument when done hook is tapped.  */
    ) => {
      console.log('Hello World!');
    });
  }
}

module.exports = HelloWorldPlugin;

这里回调函数的参数 stats 其实结构如下:


image.png

然后,要安装这个插件,只需要在你的 webpack 配置的 plugin 数组中添加一个实例:

// webpack.config.js
var HelloWorldPlugin = require('hello-world');

module.exports = {
  // ... configuration settings here ...
  plugins: [new HelloWorldPlugin({ options: true })]
};

还可以使用' schema-utils '来验证通过插件 options 选项传递的参数。这里有一个例子:

import validateOptions from 'schema-utils';

// schema for options object
const schema = {
  type: 'object',
  properties: {
    test: {
      type: 'string'
    }
  }
};

export default class HelloWorldPlugin {

  constructor(options = {}){
    validateOptions(schema, options, {
        name: 'hello-world-plugin', // 报错时,输出的插件名名称。其他配置项参考 schema-utils 文档
    });
  }

  apply(compiler) {}
}

4. Compiler 和 Compilation

在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。

这两个组件是任何 webpack 插件不可或缺的部分(特别是 compilation),因此,开发者在阅读源码,并熟悉它们之后,会感到获益匪浅:

class HelloCompilationPlugin {
  apply(compiler) {
    // Tap into compilation hook which gives compilation as argument to the callback function
    compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => {
      // Now we can tap into various hooks available through compilation
      compilation.hooks.optimize.tap('HelloCompilationPlugin', () => {
        console.log('Assets are being optimized.');
      });
    });
  }
}

module.exports = HelloCompilationPlugin;

有关compiler、compillation 和其他重要对象的钩子列表,请参阅plugins API文档。

参考

writing-a-plugin
创建插件
api/plugins/
cn/api/plugins/
schema-utils

上一篇 下一篇

猜你喜欢

热点阅读