webpack 插件怎么写

摘要

如今项目大部分都使用webpack 进行编译,一方面 webpack 生命力比较旺盛,另外一方面 webpack 的生态很是完善。咱们90%的场景都可以知足。但有时候也会遇到一些特定的业务场景,好比有时候会遇到须要对编译后的文件进行一些文件注入 等其余特定化的需求。怎么办呢?那就来写一个业务定制化的webpack 插件吧。webpack

官方文档可见: https://webpack.js.org/contribute/writing-a-plugin/#creating-a-pluginweb

如何编写插件

首先咱们了解下一个插件的主要结构api

class DtoolPlugin {
    // 构造函数,进行参数校验等功能
    constructor(args) {}
    
    // 定义插件执行的方法体,主要逻辑都在这里完成,webpack 会自动调用此方法
    apply(compiler) {}

}

下面咱们来看下 compiler 这个关键对象,compile 提供了 webpack 一系列操做的钩子函数,下面说一说经常使用的hooksapp

官方文档可见:https://webpack.js.org/api/compiler-hooks/#watching异步

下面以真实案例来说解async

apply(compiler) {
            const metaParams = this.metaParams;
        const tester = {test: this.test};

        compiler.hooks.compilation.tap('DtoolPlugin', (compilation) => {
                compilation.hooks.optimizeChunkAssets.tapAsync('DtoolPlugin', (chunks, done) => {
                    wrapChunks(compilation, chunks);
                    done();
                })
            });
            // 注入文件方法
            function wrapChunks(compilation, chunks) {
                chunks.forEach(chunk => {
                    const args = {
                        hash: compilation.hash,
                        chunkhash: chunk.hash
                    };
                    chunk.files.forEach(fileName => {
                        if (ModuleFilenameHelpers.matchObject(tester, fileName)) {
                            const content = 'xxxxx';
                            // 注入内容
                            // assets 对象是编译后的对象,以文件名为key , 值为文件内容 、 文件size 等一系列信息, 经过asset 能够对文件名字 , 文件内容作变动
                            compilation.assets[fileName] = new ConcatSource(
                                compilation.assets[fileName],
                                String(content),
                            );
                    }
                });
            });
        }
    }

hooks 调用的时候有个类型 plugin types 支持 tap , 有些支持异步类型 tapAsync tapPromise函数

compiler.hooks.run.tapAsync('MyPlugin', (source, target, routesList, callback) => {
  console.log('Asynchronously tapping the run hook.');
  callback();
});

compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
  return new Promise(resolve => setTimeout(resolve, 1000)).then(() => {
    console.log('Asynchronously tapping the run hook with a delay.');
  });
});

compiler.hooks.run.tapPromise('MyPlugin', async (source, target, routesList) => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log('Asynchronously tapping the run hook with a delay.');
});
相关文章
相关标签/搜索