webpack plugin 透过现象看本质

温馨提示:前面讲解部分大概需要花费您2分钟时间

这是使用 vue-cli 编译过后的输出显示
在这里插入图片描述
是不是看起来不是很对你的胃口,是不是想改改样式看起来好看点,是不是想输出的内容丰富点,比如编译后的文件详情,比如编译过程的日志,快速定位编译中产生的错误…

1改样式:

那么问题来了,如何找到这是在什么地方输出的,以及如何修改它:

首先我们知道 laoder 和 plugin 是 webpack 中最核心也是扩展性最高的地方,这控制台的输出是在编译的末尾,所以我们到 plugin 中找答案 ,这里我们不得不拿出 tapable这个包简单讲解下 tapable 是webpack 的核心库 主要提供的是同步异步的hook ,也就是订阅发布模式的一种实现。要修改原有的插件输出就要到tapable 中找答案 官方文档中有这么一段介绍

在这里插入图片描述
所以 我们可以自己添加一层拦截来处理:

Object.keys(compiler.hooks).forEach((item, index) => {
      compiler.hooks[item].intercept({
        register: (tapInfo) => {
          const pluginName = tapInfo.name.split(' ')[0];
          if (pluginName === 'vue-cli-service') {
            return { ...tapInfo,
              fn: (stats) => {
                const vueCliConfig = require(`${process.cwd()}/vue.config.js`);
                const vueCliConfigPort = vueCliConfig.devServer && vueCliConfig.devServer.port;
                console.log(`${chalk.white('─────────')} You application is running here ${chalk.white('─────────')}`);
                console.log(boxen(`On Your Network: ${chalk.green('http://' + getIp() + ':' + vueCliConfigPort)}`, { borderColor: 'blue', padding: 1, borderStyle: 'double' }));
                console.log(`${chalk.white('───────────────────────────────────────────────────')}`);
                console.log(`${chalk.white('───────────────────────────────────────────────────')}`);
                console.log(`${chalk.white('───────────────────────────────────────────────────')}`);
                console.log(`${chalk.gray('Or if you have any ideas, please let me know.')}`);
              } };
          }
          return tapInfo;
        }
      });
    });

修改后的输出(在开发环境)
在这里插入图片描述
下面横线部分可以自由发挥您的想象了,可以随便折腾只要你开心 ^ _ ^

2. 我们还要输出编译的详情

首先详情是要在编译完成之后输出的,这里我们并不打算直接tap webpack的钩子,而是自己给他加一个hook ,当然这是指问了提高我们对他的认知,

compiler.hooks.printFileSizesAfterBuildHook = new SyncHook(['data']);

然后在他的environment钩子上挂在我们的钩子

compiler.hooks.printFileSizesAfterBuildHook = new SyncHook(['data']);
    compiler.hooks.environment.tap(this.pluginName, () => {
      const appBuild = compiler.options.output.path;
      // 广播自定义hook
      compiler.hooks.printFileSizesAfterBuildHook.call(this.measureFileSizesBeforeBuild(appBuild));
    });

接下来我们就可以定义我们的createLog方法输出日志:

createLog (compiler) {
    const appBuild = compiler.options.output.path;
    compiler.hooks.printFileSizesAfterBuildHook.tap('Listen4Myplugin', (FileSizesAfterBuild) => {
      FileSizesAfterBuild.then((previousFileSizes) => {
        fse.emptyDirSync(appBuild);
        console.log(chalk.blue('Production environment directory has been deleted !'));
        compiler.hooks.done.tapAsync('getStats', (stats, callback) => {
          let content = ``;
          content += json.plain(stats.toJson());
          var buffer = Buffer.from(content);

          const logFile = `${this.options.path || stats.compilation.options.context || 'log'}/${this.options.filename || 'compilation-detail.md'}`;
          fse.ensureFileSync(logFile);
          let ws = fs.createWriteStream(logFile, { start: 0 });
          console.log(chalk.blueBright('Start outputting the compilation log...'));
          ws.write(buffer, 'utf8', (err) => {
            if (err) {
              throw err;
            }
            console.log(`\n`);
            console.log(chalk.blueBright(`Packing logs in this -> ${this.options.path || stats.compilation.options.context}/${this.options.filename || 'compilation-detail.md'}`));
            console.log(`\n`);
            WARN_AFTER_BUNDLE_GZIP_SIZE = this.options.warnAfterBundleGzipSize || WARN_AFTER_BUNDLE_GZIP_SIZE;
            WARN_AFTER_CHUNK_GZIP_SIZE = this.options.warnAfterChunkGzipSize || WARN_AFTER_BUNDLE_GZIP_SIZE;
            this.printFileSizesAfterBuild(
              stats,
              previousFileSizes,
              appBuild,
              WARN_AFTER_BUNDLE_GZIP_SIZE,
              WARN_AFTER_CHUNK_GZIP_SIZE,
              callback
            );
          });
        });
      });
    });
  }

注意这里的compiler.hooks.printFileSizesAfterBuildHook 就是我们挂载到webpack 中的自定义的hook,完了之后定义相应的方法输出分别以文件和命令行的形式输出日志即可
在这里插入图片描述
当然这里也是随您需求自己改动的。是不是很方便,同时我们也会以文件的形式输出整个编译的详情,包括您需要的那些莫名奇妙的错误都可以在日志中的
warnings和errors中快速定位在这里插入图片描述
喜欢的话 记得点个 star
或者有是什么问题欢迎加我微信互相交流学习 nikeshope

发布了77 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37653449/article/details/97047986