imagemin-webpack-plugin
2024年04月06日
一、认识
imagemin-webpack-plugin
是一个用于实现图像压缩的插件,它会在 Webpack
完成前置的代码分析构建,提交(emit
)产物时,找出所有图片资源并调用 imagemin
压缩图像。主要逻辑如下:
-
通过
compiler.hooks.emit
钩子, 在Webpack
完成代码构建与打包操作,准备将产物发送到输出目录之前执行 -
通过
.tapAsync
异步调用optimizeWebpackImages
函数完成图像压缩操作 -
在
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) {}
}