Webpack Plugin学习笔记

444 阅读2分钟

webpack工作流程

webpack根据打包流程定义了不同阶段的事件集。在打包过程中,通过调用预先在事件集中注册事件,实现特定的处理功能,完成自定义打包

plugin 即是通过webpack事件机制,执行具体自定义任务的抽象接口

Plugin基本结构
class Plugin {
    constructor(option) {}
    // 为事件添加监听函数
    apply(complier) {}
}
plugin执行流程
  • webpack初始化后,在读取plugins属性时初始化所有plugins插件
  • 通过调用插件的apply函数(应用complier参数)将处理功能函数注册至webpack各个阶段中
  • webpack按事件流的触发顺序,调用plugin在各个阶段注册的函数(应用compilation参数获取当前编译对象)

事件机制

webpack内部通过Tapable库实现事件机制(注册、触发): 详情看tapbale

Webpack主要对象

  • compiler: 完整的webpack环境配置对象。
  • complilation: 一次资源版本构建对象。每当检测到一个文件变化,就会创建一个新的compilation,生成一组新的编译资源; complilation对象包含了当前模块资源、编译生成资源、变化文件、跟踪依赖的状态信息; 同时以提供了很多关键时机的回调,以供插件做自定义处理
Compiler(编译实例)
class Compiler {
    constructor(context) {
        // 定义各阶段(生命周期)的hooks名称
        this.hooks = Object.freeze({
            done: new AsyncSeriesHook(["stats"]),//一次编译完成后执行,回调参数:stats
            beforeRun: new AsyncSeriesHook(["compiler"]),
            run: new AsyncSeriesHook(["compiler"]),//在编译器开始读取记录前执行
            emit: new AsyncSeriesHook(["compilation"]),//在生成文件到output目录之前执行,回调参数: compilation
            afterEmit: new AsyncSeriesHook(["compilation"]),//在生成文件到output目录之后执行
            compilation: new SyncHook(["compilation", "params"]),//在一次compilation创建后执行插件
            beforeCompile: new AsyncSeriesHook(["params"]),
            compile: new SyncHook(["params"]),//在一个新的compilation创建之前执行
            make:new AsyncParallelHook(["compilation"]),//完成一次编译之前执行
            afterCompile: new AsyncSeriesHook(["compilation"]),
            watchRun: new AsyncSeriesHook(["compiler"]),
            failed: new SyncHook(["error"]),
            watchClose: new SyncHook([]),
            afterPlugins: new SyncHook(["compiler"]),
            entryOption: new SyncBailHook(["context", "entry"])
        });
        // WebpackOptions: webpack.config.js配置信息
        this.options = {}
        // webpack构建函数
        this.webpack = webpack
        // 上下文路径 {string}
        this.context = context
        // ...
    }
    // 创建Compilation对象
    newCompilation(params) {}
    // watch监听
    watch() {}
    // 打包流程(即完整的生命周期)
    run(callback) {}
    // 编译流程
    compile(callback) {}
    // 生成打包文件
    emitAssets(compilation, callback) {}
}

详细看www.webpackjs.com/api/compile…

Compilation(正在编译实例)

每次监听到新的编译(或新的构建),如chunks,就会创建一个新的 compilation,执行编译

与Compiler用法类似,属性中有compiler的指针

详细看www.webpackjs.com/api/compila…

自定义Plugin
class MyPlugin {
    // 自定义配置
    constructor(options) {
        this.filename = options.filename
    }
    apply(complier) {
        // context 为 运行指令的目录
        const context = compiler.options.context // process.cwd()
        
        // 在各个阶段添加执行函数(钩子)
        compiler.hooks.emit.tap('pluginName', (complication) => {
            // (1)在compiler钩子阶段执行
            
            // (2)在compliation钩子阶段执行
            compilation.hooks.additionalAssets.tapAsync('name', (cb) => {
                const content = 'hello world'
                // 方式一:
                compilation.assets['a.txt'] = {
                    source() { return content },
                    size() {return content.length}
                }
                // 方式二:
                compliation.assets['b.txt'] = new RawSource(content)
                // 方法三:
                compliation.emitAsset('c.txt', new RawSource(content))

                cb()
            })
        })
    }
}