// 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;