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)
(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();
});
});
}
}