案例实战之如何写一个webpack plugin

Posted 行果、

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了案例实战之如何写一个webpack plugin相关的知识,希望对你有一定的参考价值。

案例实战之如何写一个webpack plugin

1.写一个生成打包文件目录的file.md文件

// 生成一个目录项目目录的文件夹
class FileListPlugin {
    constructor(options) {
        this.options = options
    }
    apply(compiler) {
        compiler.hooks.emit.tap(\'fileListPlugin\', (compilation) => {
            let assets = compilation.assets
            let content = \'In this build:\\r\\n\'
            Object.entries(assets).forEach(([fileName, fileSize]) => {
                content += `--${fileName} —— ${Math.ceil(fileSize.size() / 1024)}kb\\r\\n`
            })
            console.log(\'====content====\', content)
            assets[this.options.filename] = {
                source() {
                    return content
                },
                size() {
                    return content.length
                }
            }
        })
    }
}
module.exports = FileListPlugin


使用

const FileListPlugin = require(\'./plugins/fileListPlugin.js\')
plugins:[
    new FileListPlugin({
            filename: \'filelist.md\'
    }),
]

生成的结果如下

![image-20191206173728326](F:\\myobject\\vue2\\myb

2.写一个生成版权信息的copyright文件的插件

class CopyRightWebpackPlugin {
    constructor(options) {
        this.options = options
    }
    apply(compiler) {
        compiler.hooks.compile.tap(\'webpackCompiler\', () => {
            console.log(\'compiler\')
        })
        compiler.hooks.emit.tapAsync(\'CopyRightWebpackPlugin\', (compilation, cb) => {
            compilation.assets[this.options.filename] = {
                source() {
                    return \'copyRight by heibao\'
                },
                size() {
                    return 25
                }
            }
            cb()
        })
    }
}
module.exports = CopyRightWebpackPlugin

webpack 的源码compiler钩子函数是借助tapable库实现的

const {
    Tapable,
    SyncHook,
    SyncBailHook,
    AsyncParallelHook,
    AsyncSeriesHook
} = require("tapable");
class Compiler extends Tapable {
    constructor(context) {
        super();
        this.hooks = {
            /** @type {SyncBailHook<Compilation>} */
            shouldEmit: new SyncBailHook(["compilation"]),
            /** @type {AsyncSeriesHook<Stats>} */
            done: new AsyncSeriesHook(["stats"]),
            /** @type {AsyncSeriesHook<>} */
            additionalPass: new AsyncSeriesHook([]),
            /** @type {AsyncSeriesHook<Compiler>} */
            beforeRun: new AsyncSeriesHook(["compiler"]),
            /** @type {AsyncSeriesHook<Compiler>} */
            run: new AsyncSeriesHook(["compiler"]),
            /** @type {AsyncSeriesHook<Compilation>} */
            emit: new AsyncSeriesHook(["compilation"]),
            /** @type {AsyncSeriesHook<string, Buffer>} */
            assetEmitted: new AsyncSeriesHook(["file", "content"]),
            /** @type {AsyncSeriesHook<Compilation>} */
            afterEmit: new AsyncSeriesHook(["compilation"]),

            /** @type {SyncHook<Compilation, CompilationParams>} */
            thisCompilation: new SyncHook(["compilation", "params"]),
            /** @type {SyncHook<Compilation, CompilationParams>} */
            compilation: new SyncHook(["compilation", "params"]),
            /** @type {SyncHook<NormalModuleFactory>} */
            normalModuleFactory: new SyncHook(["normalModuleFactory"]),
            /** @type {SyncHook<ContextModuleFactory>}  */
            contextModuleFactory: new SyncHook(["contextModulefactory"]),

            /** @type {AsyncSeriesHook<CompilationParams>} */
            beforeCompile: new AsyncSeriesHook(["params"]),
            /** @type {SyncHook<CompilationParams>} */
            compile: new SyncHook(["params"]),
            /** @type {AsyncParallelHook<Compilation>} */
            make: new AsyncParallelHook(["compilation"]),
            /** @type {AsyncSeriesHook<Compilation>} */
            afterCompile: new AsyncSeriesHook(["compilation"]),

            /** @type {AsyncSeriesHook<Compiler>} */
            watchRun: new AsyncSeriesHook(["compiler"]),
            /** @type {SyncHook<Error>} */
            failed: new SyncHook(["error"]),
            /** @type {SyncHook<string, string>} */
            invalid: new SyncHook(["filename", "changeTime"]),
            /** @type {SyncHook} */
            watchClose: new SyncHook([]),

            /** @type {SyncBailHook<string, string, any[]>} */
            infrastructureLog: new SyncBailHook(["origin", "type", "args"]),

            // TODO the following hooks are weirdly located here
            // TODO move them for webpack 5
            /** @type {SyncHook} */
            environment: new SyncHook([]),
            /** @type {SyncHook} */
            afterEnvironment: new SyncHook([]),
            /** @type {SyncHook<Compiler>} */
            afterPlugins: new SyncHook(["compiler"]),
            /** @type {SyncHook<Compiler>} */
            afterResolvers: new SyncHook(["compiler"]),
            /** @type {SyncBailHook<string, Entry>} */
            entryOption: new SyncBailHook(["context", "entry"])
        };
    }}

上面的钩子函数是在webpack解析代码的不同周期执行的

以上是关于案例实战之如何写一个webpack plugin的主要内容,如果未能解决你的问题,请参考以下文章

webpack实战之手写一个loader和plugin

webpack配置之自定义loader

Webpack-源码三,从源码分析如何写一个plugin

webpck深入浅出教程如何写一个plugin

案例实战:每日上亿请求量的电商系统,JVM年轻代垃圾回收参数如何优化?

如何编写一个WebPack的插件原理及实践