跳到主要内容

imagemin-webpack-plugin

2024年04月06日
柏拉文
越努力,越幸运

一、认识


imagemin-webpack-plugin 是一个用于实现图像压缩的插件,它会在 Webpack 完成前置的代码分析构建,提交(emit)产物时,找出所有图片资源并调用 imagemin 压缩图像。主要逻辑如下:

  1. 通过 compiler.hooks.emit 钩子, 在 Webpack 完成代码构建与打包操作,准备将产物发送到输出目录之前执行

  2. 通过 .tapAsync 异步调用 optimizeWebpackImages 函数完成图像压缩操作

  3. optimizeWebpackImages 内部, 遍历 assets 产物数组, 读取产物内容, 并尝试从缓存中读取, 调用 imagemin 压缩图片, 之后,使用优化版本替换原始文件

二、实现


export default class ImageminPlugin {
constructor(options = {}) {
// init options
}

apply(compiler) {
// ...
const onEmit = async (compilation, callback) => {
// ...
await Promise.all([
...this.optimizeWebpackImages(throttle, compilation),
...this.optimizeExternalImages(throttle),
]);
};

compiler.hooks.emit.tapAsync(this.constructor.name, onEmit);
}

optimizeWebpackImages(throttle, compilation) {
const {
// 用于判断是否对特定文件做图像压缩操作
testFunction,
// 缓存目录
cacheFolder
} = this.options

// 遍历 `assets` 产物数组
return map(compilation.assets, (asset, filename) => throttle(async () => {
// 读取产物内容
const assetSource = asset.source()
if (testFunction(filename, assetSource)) {
// 尝试从缓存中读取
let optimizedImageBuffer = await getFromCacheIfPossible(cacheFolder, assetSource, () => {
// 调用 `imagemin` 压缩图片
return optimizeImage(assetSource, this.options)
})

// 之后,使用优化版本替换原始文件
compilation.assets[filename] = new RawSource(optimizedImageBuffer)
}
}))
}

optimizeExternalImages(throttle) {}
}