wand-front-utils/imagemin-jpgify-webpack-plugin.js
2020-04-19 20:23:53 -07:00

119 lines
4.5 KiB
JavaScript

// Sourced from: https://raw.githubusercontent.com/iampava/imagemin-jpegify-webpack-plugin/master/plugin.js
const imagemin = require('imagemin');
const jpegify = require('png-to-jpeg');
const GREEN = '\x1b[32m%s\x1b[0m';
const RED = '\x1b[31m%s\x1b[0m';
class ImageminJpegifyWebpackPlugin {
constructor({
config = [
{
test: /\.(png)/,
options: {
quality: 50
}
}
],
overrideExtension = true,
detailedLogs = false,
strict = true,
silent = false
} = {}) {
this.config = config;
this.detailedLogs = detailedLogs;
this.strict = strict;
this.overrideExtension = overrideExtension;
this.silent = silent;
}
apply(compiler) {
const onEmit = (compilation, cb) => {
let assetNames = Object.keys(compilation.assets);
let nrOfImagesFailed = 0;
if (this.silent && this.detailedLogs) {
compilation.warnings.push(new Error(`ImageminJpegifyWebpackPlugin: both the 'silent' and 'detailedLogs' options are true. Overriding 'detailedLogs' and disabling all console output.`));
}
Promise.all(
assetNames.map(name => {
for (let i = 0; i < this.config.length; i++) {
if (this.config[i].test.test(name)) {
let outputName = name;
if (this.overrideExtension) {
outputName = outputName
.split('.')
.slice(0, -1)
.join('.');
}
outputName = `${outputName}.jpg`;
let currentAsset = compilation.assets[name];
return imagemin
.buffer(currentAsset.source(), {
plugins: [jpegify(this.config[i].options)]
})
.then(buffer => {
let savedKB = (currentAsset.size() - buffer.length) / 1000;
if (this.detailedLogs && !this.silent) {
console.log(GREEN, `${savedKB.toFixed(1)} KB saved from '${name}'`);
}
compilation.assets[outputName] = {
source: () => buffer,
size: () => buffer.length
};
return savedKB;
})
.catch(err => {
let customErr = new Error(`ImageminJpegifyWebpackPlugin: "${name}" wasn't converted!`);
nrOfImagesFailed++;
if (this.strict) {
compilation.errors.push(err, customErr);
} else if (this.detailedLogs) {
compilation.warnings.push(err, customErr);
}
return 0;
});
}
}
return Promise.resolve(0);
})
).then(savedKBArr => {
if (!this.silent) {
let totalKBSaved = savedKBArr.reduce((acc, cur) => acc + cur, 0);
if (totalKBSaved < 100) {
console.log(GREEN, `imagemin-jpegify-webpack-plugin: ${Math.floor(totalKBSaved)} KB saved`);
} else {
console.log(GREEN, `imagemin-jpegify-webpack-plugin: ${Math.floor(totalKBSaved / 100) / 10} MB saved`);
}
if (nrOfImagesFailed > 0) {
console.log(RED, `imagemin-jpegify-webpack-plugin: ${nrOfImagesFailed} images failed to convert to webp`);
}
}
cb();
});
};
if (compiler.hooks) {
// webpack 4.x
compiler.hooks.emit.tapAsync('ImageminJpegifyWebpackPlugin', onEmit);
} else {
// older versions
compiler.plugin('emit', onEmit);
}
}
}
module.exports = ImageminJpegifyWebpackPlugin;