webpack学习笔记二 编写一个webpack插件,将生产包压缩后输出

49 阅读3分钟

在编写webpack插件的时候,首先需要了解webpack的生命周期,webpack的生命周期指的是webpack在构建过程中的各个阶段,每个阶段都与不同的任务和钩子相关。下面列举一些可能会使用到的钩子

  1. run

    • 当开始执行Webpack构建时触发。
    • 相关钩子:compiler.hooks.run
  2. compile

    • 在每次编译中触发,表示开始一个新的编译。
    • 相关钩子:compiler.hooks.compile
  3. compilation

    • 在每次新的编译创建时触发。
    • 相关钩子:compiler.hooks.thisCompilation
  4. make

    • 在每个编译中执行构建任务之前触发。
    • 相关钩子:compiler.hooks.make
  5. build-module

    • 在每个模块构建之前触发。
    • 相关钩子:compilation.hooks.buildModule
  6. optimize-modules

    • 在模块优化阶段触发,用于优化和准备模块。
    • 相关钩子:compilation.hooks.optimizeModules
  7. optimize-chunks

    • 在块(chunk)优化阶段触发,用于优化和准备块。
    • 相关钩子:compilation.hooks.optimizeChunks
  8. optimize-tree

    • 在优化模块和块的树结构时触发。
    • 相关钩子:compilation.hooks.optimizeTree
  9. after-optimize-chunks

    • 在块优化完成后触发。
    • 相关钩子:compilation.hooks.afterOptimizeChunks
  10. emit

    • 在构建过程中生成最终资源并输出到输出目录之前触发。
    • 相关钩子:compilation.hooks.processAssets
  11. after-emit

    • 在资源输出完成后触发。
    • 相关钩子:compilation.hooks.afterEmit
  12. done

    • 当构建完成时触发。
    • 相关钩子:compiler.hooks.done

插件通过订阅这些生命周期的钩子,可以在构建的不同阶段执行自定义逻辑。例如,可以在emit阶段生成文件,或在done阶段执行一些清理操作。

apply函数

webpack插件是一个Javascript类,他需要包含一个名为 ·apply·的方法,这个方法会在Webpack编译时被调用

class MyPlugin {
  constructor(options) {
    // 在构造函数中可以接收插件的配置选项
    this.options = options || {};
  }

  // apply函数是插件的入口点,它会在Webpack编译时被调用
  apply(compiler) {
    // 注册一个Webpack钩子,以便在构建过程中执行插件逻辑
    compiler.hooks.beforeRun.tap('MyPlugin', (params) => {
      // 插件逻辑
      console.log('我的插件执行了,在构建开始时!', params);
    });
  }
}

module.exports = MyPlugin;

  • apply方法是每个插件的入口点,它会在Webpack编译时被调用。
  • apply方法接收一个compiler参数,这是Webpack的编译器对象。通过编译器对象,插件可以访问Webpack的各种功能和钩子。
  • apply方法中,你可以注册各种Webpack的钩子(hooks),以便在构建过程中执行插件的逻辑。上面的例子中,我们注册了一个名为beforeRun的钩子,当这个钩子被触发时,插件的逻辑将被执行。

构建一个在打包结束后,能够将输出的包压缩成.zip的插件

  • 我们需要依赖 archiver 这个包
npm install archiver
  • 构建这个插件
const archiver = require('archiver');
const fs = require('fs');
const path = require('path');

class ZipPlugin {
apply(compiler) {
  compiler.hooks.done.tap('ZipPlugin', (stats) => {
    const outputPath = stats.compilation.outputOptions.path;
    const outputFolderPath = path.basename(outputPath); // 获取输出文件夹的名称
    const outputFilePath = path.join(outputPath, '..', `${outputFolderPath}.zip`); // 在同级目录下生成压缩包

    const output = fs.createWriteStream(outputFilePath);
    const archive = archiver('zip', {
      zlib: { level: 9 },
    });

    output.on('close', () => {
      console.log(`Zip file created: ${outputFilePath}`);
    });

    archive.on('error', (err) => {
      console.error('Error while zipping:', err);
    });

    archive.pipe(output);

    // 将输出文件夹的内容添加到压缩包
    archive.directory(outputPath, false);

    archive.finalize();
  });
}
}

module.exports = ZipPlugin;
  • 将这个插件添加到 Webpack配置中。webpack.config.js
const ZipPlugin = require('./ZipPlugin');

module.exports = {
// ...其他配置

plugins: [
 new ZipPlugin(),
],
};