webpack中的plugin 且 手写一个简单的plugin

2023-5-26 899 5/26

plugin:插件,webpack的核心之一,对webpack能力的扩展,他能做的事情很多,如:打包优化,资源管理,注入环境变量这些。

 

借用深入浅出 Webpack来解释先webpack中的plugin:

webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。 插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。webpack 通过 Tapable 来组织这条复杂的生产线。 webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。 webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。

也就是webpack 在编译代码过程中,会触发一系列 Tapable 钩子事件,插件所做的,就是找到相应的钩子,往上面挂上自己的任务,也就是注册事件,这样,当 webpack 构建的时候,插件注册的事件就会随着钩子的触发而执行了。

Tapable 还统一暴露了三个方法给插件,用于注入不同类型的自定义构建行为:

  • tap:可以注册同步钩子和异步钩子。
  • tapAsync:回调方式注册异步钩子。
  • tapPromise:Promise 方式注册异步钩子

 

插件的基本构成:

首先一个 Plugin 应该是一个 class,当然也可以是一个函数。

其次 Plugin 的原型对象上应该存在一个 apply 方法,当 webpack 创建 compiler 对象时会调用各个插件实例上的 apply 方法并且传入 compiler 对象作为参数。

同时需要指定一个绑定在 compiler 对象上的 Hook , 比如 compiler.hooks.done.tap 在传入的 compiler 对象上监听 done 事件。

在 Hook 的回调中处理插件自身的逻辑,

根据 Hook 的种类,在完成逻辑后通知 webpack 继续进行

一个简单的插件demo

class TestPlugin {
    constructor() {
        console.log("my test plugin");
    }
    apply(compiler) {
        console.log("TestPlugin的apply方法调用");
        // console.log(compiler,'compiler对象');
       //同步钩子
        compiler.hooks.compile.tap("TestPlugin", (compilationParams) => {
            console.log("compiler.compile()");
        });

       //异步钩子

        compiler.hooks.make.tap("TestPlugin", (compilation) => {
            setTimeout(() => {
                console.log("compiler.make()");
            }, 2000);
        });
    }
}
module.exports = TestPlugin;

使用的话在webpack.config.js文件中引入,然后调用就行,

  plugins: [
new TestPlugin()
  ],

运行看一下webpack中的plugin 且 手写一个简单的plugin

 

plugin的构建对象,核心

compiler 对象中保存着完整的 Webpack 环境配置,每次启动 webpack 构建时它都是一个独一无二,仅仅会创建一次的对象。

这个对象会在首次启动 Webpack 时创建,我们可以通过 compiler 对象上访问到 Webapck 的主环境配置,比如 loader 、 plugin 等等配置信息。

compiler.hooks 可以注册 tapable 的不同种类 Hook,从而可以在 compiler 生命周期中植入不同的逻辑。

 

compilation 对象代表一次资源的构建,compilation 实例能够访问所有的模块和它们的依赖。

一个 compilation 对象会对构建依赖图中所有模块,进行编译。 在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、 分块(chunk)、哈希(hash)和重新创建(restore)

compilation.hooks 可以注册 tapable 的不同种类 Hook,用于在 compilation 编译模块阶段进行逻辑添加以及修改

主要属性:modules,chunks(由多个modules组成的代码块),assets(本次打包所生成文件的所有结果),hooks(tapable提供的一系列钩子)

 

具体的属性可以去查看官方的文档。

 

实现一个简单的注释插件,

class MyPlugin {
    constructor(options = {}) {
        this.options = options;
    }

    apply(compiler) {
        // 需要处理文件
        compiler.hooks.emit.tapAsync("MyPlugin", (compilation, callback) => {

            console.log('给所有的打包文件添加注释');
            Object.keys(compilation.assets).forEach((assetPath) => {
                const asset = compilation.assets[assetPath];
                const source =
                    `/*
    * 当前的文件: ${assetPath}
    */\n${asset.source()}`;// 生成新的资源内容

                // 覆盖资源
                compilation.assets[assetPath] = {
                    // 资源内容
                    source() {
                        return source;
                    },
                    // 资源大小
                    size() {
                        return source.length;
                    },
                };
            });

            callback();
        });
    }
}
module.exports = MyPlugin;

 

webpack中的plugin 且 手写一个简单的plugin

 

 

 

- THE END -
0

共有 0 条评论