如何手写一个webpack插件(plugin)

923 阅读2分钟

如何手写一个webpack插件(plugin)呢?
其实我的想法比较简单,看看webpack怎么调用他自己内部插件的流程不就好了嘛。
我这里拿webpack4来举个例子。
随便从webpack lib目录下找一个插件,就比如NodeEnvironmentPlugin这个插件

image.png 在或者EnsureChunkConditionsPlugin这个插件

image.png 干脆直接打开WebpackOptionsApply这个文件看看调用插件的例子,我们可以看到都是以new起手,紧接着一调用apply,再传入compiler。那我们直接创建一个这样的类行不行呢。
1、首先创建一个TestPlugin文件、在文件里创建一个类

// TestPlugin.js
class TestPlugin {

}

2、接着定义一个apply方法,并拿到实参compiler(上面也看到了,webpack内部调用插件的时候都会传入compiler实例)

// TestPlugin.js
class TestPlugin {
    apply(compiler) {
        
    }
}

3、这里我们做一个小的案例:在webpack输出后的文件夹里创建一个我们自己的文件,并打印一句话(很简单吧)
那我们就要看看这个compiler里面有什么东西了

image.png 首先会看到wcompiler实例里面会有很多钩子函数,具体可以去官方文档去了解一下

image.png 还有一些属性,那我就猜我们这个案例要创建文件,应该和file有关,那我们能不能用到这个outputPathoutputFileSystem,让我们试试

// TestPlugin.js
class TestPlugin {
    apply(compiler) {
        compiler.hooks.emit.tap('TestPluginEmit', () => {
            compiler.outputFileSystem.writeFile(compiler.outputPath+ '/TestPluginOut.js', '//我们的第一个webpack插件!', () => {})
        })
    }
}

好,我们的第一个插件就写完了,大致意思是在webpack钩子emit call(这是tapable实例的方法)执行的时候,会去执行我们的tap调用里面传入的函数,也就是compiler.outputFileSystem.writeFile(compiler.outputPath+ '/TestPluginOut.js', '//我们的第一个webpack插件!', () => {})
现在让我们去webpack配置文件中去引入我们的插件吧。

// webpack.config.js
const TestPlugin = require('??/TestPlugin') // 路径记得写对哦
module.exports = function() {
    return {
        mode: 'development',
        entry: ['./src/app.js'],
        output: {
            path: path.join(__dirname, 'out'),
            filename: 'out.[name].js'
        },
        plugins: [
            new TestPlugin(),
        ]
    }
}

最后可以看到我们的out目录下会多生产一个TestPluginOut.js文件,没错正是我们自己写的插件生产的。是不是觉得很好玩呢。