【webpack】插件机制模拟小案例

251 阅读1分钟

需求:将一个字符串每个字符之间用-隔开

实现这样一个类SplitChar

  1. initStr 保存要处理的字符串
  2. curStr 最终处理完的字符串
  3. hooks 对于字符串处理的个阶段实例化SyncHook
  1. run函数处理逻辑init(初始化) ,before、main、after(处理阶段)以及return(最终返回)
  2. 处理阶段又分为前置处理中收尾三个阶段,分别对应before、main、after
"use strict";
const SyncHook = require("./SyncHook");
class SplitChar {
  constructor() {
    this.initStr = "";
    this.curStr = "";
    this.hooks = {
      beforeRun: new SyncHook(["before"]),
      mainRun: new SyncHook(["main"]),
      afterRun: new SyncHook(["after"]),
    };
  }
  init(str) {
    this.initStr = str;
  }
  splitChar(str) {
    return str.split("");
  }
  before() {
    // 前置工作,判断是否有字符串
    this.hooks.beforeRun.call(this);
    if (!this.initStr) {
      return false;
    }
    return true;
  }
  main() {
    // 字符串用-隔开
    this.curStr = this.initStr.split("").join("-");
    this.hooks.mainRun.call(this);
  }
  after() {
    this.hooks.afterRun.call(this);
  }
  run(str) {
    this.init(str);
    if (this.before()) {
      this.main();
      this.after();
    }
    return this.curStr;
  }
}

直接使用

const t = new SplitChar();
const res = t.run("字符串切割暴力")
// 得到结果res "字-符-串-切-割-暴-力"

新需求

  1. 去掉敏感词暴力
  2. 连接符-改为*
  3. 最终生成的字符串拼接《处理完了》

针对新需求注册事件以及回调

const t = new SplitChar();
t.hooks.afterRun.tap("test", (t) => {
  t.curStr += "《处理完了》";
});
t.hooks.beforeRun.tap("test", (t) => {
  // 过滤敏感字
  if (typeof t.initStr !== "string") {
    t.initStr = "";
  } else {
    t.initStr = t.initStr.replace(/(暴力|疯狂)/g, "");
  }
});
t.hooks.mainRun.tap("main", (t) => {
  // 将-符号改为*
  t.curStr = t.curStr.replace(/-/g, "*");
});
const res = t.run("字符串切割暴力")
// 得到结果res "字*符*串*切*割《处理完了》"

总结

  • 由于有SyncHook的使用,可以在每个处理阶段插入事件去修改最终的结果
  • 注册事件的回调参数是SplitCharthis.hooks.afterRun.call(this)传入的this
  • 这个只是简单案例,webpack中的插件部分要比这个案例复杂的多,但思想上类似