webpack--插件

冉绯辞
2023-12-01

一、插件的运行环境

1、插件没有像 loader 那样的独立运行环境(loader-runner)

2、只能在 webpack 里面运行

二、 插件的基本结构

//插件名称
class MyPlugin {
  // 插件上的 apply 方法
  apply(compiler) {
    // 插件的 hooks
    compiler.hooks.done.tap(
      " My Plugin",
      (stats /* stats is passed as argument when done hook is tapped. */) => {
        //插件处理逻辑
        console.log("Hello World!");
      }
    );
  }
}
module.exports = MyPlugin;

三、插件使用

const path = require('path');
const ZipPlugin = require('./plugins/zip-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'main.js'
    },
    mode: 'production',
    plugins: [
        new ZipPlugin({
            filename: 'offline'
        })
    ]
}

四、开发一个最简单的插件

1、src/demo-plugin.js

module.exports = class DemoPlugin {
  constructor(options) {
    this.options = options;
  }
  apply() {
    console.log("apply", this.options);
  }
};

 2、加入到 webpack 配置中

module.exports = {
  //...
  plugins: [new DemoPlugin({ name: "demo" })],
};

五、插件中如何获取传递的参数

通过插件的构造函数进行获取

module.exports = class MyPlugin {
  constructor(options) {
    this.options = options;
  }
  apply() {
    console.log("apply", this.options);
  }
};

 六、插件的错误处理

(1)参数校验阶段可以直接 throw 的方式抛出 

throw new Error(“ Error Message”)

(2)通过 compilation 对象的 warnings errors 接收 

compilation.warnings.push("warning");
compilation.errors.push("error");

 七、插件扩展:编写插件的插件

插件自身也可以通过暴露 hooks 的方式进行自身扩展,以 html- webpack-plugin 为例

  • html-webpack-plugin-alter-chunks (Sync)
  • html-webpack-plugin-before-html-generation (Async)
  • html-webpack-plugin-alter-asset-tags (Async)
  • html-webpack-plugin-after-html-processing (Async)
  • html-webpack-plugin-after-emit (Async) 

八、编写一个压缩构建资源为zip包的插件

(1)要求

  • 生成的 zip 包文件名称可以通过插件传入 
  • 需要使用 compiler 对象上的特地 hooks 进行资源的生成

(2)Compilation 上的 assets 可以用于文件写入(可以将 zip 资源包设置到 compilation.assets 对象上)

(3)文件写入需要使用 webpack-sources

(4)使用 jszip 将文件压缩为 zip 包

var zip = new JSZip();
zip.file("Hello.txt", "Hello World\n");
var img = zip.folder("images");
img.file("smile.gif", imgData, { base64: true });
zip.generateAsync({ type: "blob" }).then(function (content) {
  // see FileSaver.js
  saveAs(content, "example.zip");
});

(5) Compiler 上负责文件生成的 hooks

  • Hooks 是 emit,是一个异步的 hook (AsyncSeriesHook)
  • emit 生成文件阶段,读取的是 compilation.assets 对象的值

(6)实现 

const JSZip = require('jszip');
const path = require('path');
const RawSource = require('webpack-sources').RawSource;
const zip = new JSZip();

module.exports = class ZipPlugin {
    constructor(options) {
        this.options = options;
    }

    apply(compiler) {
        compiler.hooks.emit.tapAsync('ZipPlugin', (compilation, callback) => {
            const folder = zip.folder(this.options.filename);

            for (let filename in compilation.assets) {
                const source = compilation.assets[filename].source();
                folder.file(filename, source);
            }

            zip.generateAsync({
                type: 'nodebuffer'
            }).then((content) => {
                const outputPath = path.join(
                    compilation.options.output.path, 
                    this.options.filename + '.zip'
                );

                const outputRelativePath = path.relative(
                    compilation.options.output.path,
                    outputPath
                );
                compilation.assets[outputRelativePath] = new RawSource(content);

                callback();
            });
        });
    }
}
 类似资料: