webpack 自定义开发 plugin

382 阅读2分钟

一、开发 plugin 之前需要做的准备

规划文件目录

 webpackPlugin
    |- package.json
    |- webpack.config.js
    |- /src
      |- index.js

package.json 文件内容

{
  "name": "webpackplugin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build": "webpack --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^4.0.0",
    "html-webpack-plugin": "^5.5.0",
    "webpack": "^5.69.1",
    "webpack-cli": "^4.9.2"
  }
}

webpack.config.js 文件内容

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'plugins'
        }),
        new CleanWebpackPlugin(),
    ]
}

index.js 随意写点即可

二、compiler、compilation 以及钩子

官方解释如下

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

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

  • hooks 钩子的本质其实就是事件,参考文档:webpack.docschina.org/api/compile…

三、从使用 plugin 分析自定义 plugin 的书写规范

例如:html-webpack-plugin的使用方法,从用法上看自定义 plugin 其实是一个类或者是一个函数,使用new可以实例化插件对象,我们可以传参,也可以接受传入的参数。

const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
    new HtmlWebpackPlugin({
        title: 'plugins'
    }),
]
class MyPlugin {
  constructor (data) {}
}
// 或者
function MyPlugin(data) {}

四、整理好心态

  • 从简单开始、很多复杂的事情可以分开几个简单的 case 来完成
  • 把官方文档看成我们的工具包,需要什么去里面找

五、开发我们第一个 plugin

插件功能:打包完成之后,控制台会输出一个 "这是我的第一个自定义插件~"

  • 创建一个文件夹:plugins
  • plugins 文件夹下创建文件 onePlugin.js
  • done: 打包编译之后的钩子函数
  • 三种触发钩子的方法
    1. tap :以同步方式触发钩子;
    2. tapAsync :以异步方式触发钩子;
    3. tapPromise :以异步方式触发钩子,返回 Promise;

onePlugin.js 文件的代码如下:

const pluginName = 'OnePlugin';
class OnePlugin {
    constructor(options) {
        // 接受外部传入的参数
        this.options = options
    }
    
    // apply 函数一定要有
    apply(compiler) {
        // done 打包完成之后用到的钩子函数并且执行
        compiler.hooks.done.tap(pluginName, (compilation,callback)=> {
            console.log(this.options.message)
        })
    }
}

module.exports = OnePlugin

webpack.config.js文件引入插件

const OnePlugin = require('./plugins/onePlugin')
plugins: [
    new OnePlugin({message: '这是我的第一个自定义插件~'})
]

执行npm run build控制台输出如下:

截屏2022-02-18 下午5.20.30.png

控制台已经输出了:这是我的第一个自定义插件~,此刻应该给自己 👏 👏 👏🏻