diff --git a/src/index.js b/src/index.js index d68f54c..cfb0acc 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,7 @@ const Figures = require("figures"); const Ora = require("ora"); const SchemaUtils = require("schema-utils"); const { ByteSize, RoundNum } = require("trample/node"); +const { RawSource } = require("webpack-sources"); const { IMG_REGEXP, PLUGIN_NAME } = require("../util/getting"); const { RandomHeader } = require("../util/setting"); @@ -18,32 +19,41 @@ module.exports = class TinyimgWebpackPlugin { apply(compiler) { const { enabled, logged } = this.opts; SchemaUtils(Schema, this.opts, { name: PLUGIN_NAME }); - enabled && compiler.hooks.emit.tap(PLUGIN_NAME, compilation => { + enabled && compiler.hooks.emit.tapPromise(PLUGIN_NAME, compilation => { const imgs = Object.keys(compilation.assets).filter(v => IMG_REGEXP.test(v)); if (!imgs.length) return Promise.resolve(); const promises = imgs.map(v => this.compressImg(compilation.assets, v)); - const spinner = Ora("Image is compressing......").start(); - return Promise.all(promises).then(res => { - spinner.stop(); - logged && res.forEach(v => console.log(v)); - }); + const spinner = Ora("Images is compressing......").start(); + return new Promise(resolve => { + Promise.all(promises).then(res => { + spinner.stopAndPersist({text: 'Images compression done', symbol: '✅'}); + // 输出错误,如果有的话 + res.filter(info => logged || info.status === 'fail').forEach(v => console.log(v.msg)); + resolve() + }) + }) }); } async compressImg(assets, path) { try { const file = assets[path].source(); const obj = await this.uploadImg(file); + + if (obj.isError) { + return Promise.resolve({msg: `${Figures.cross} [${Chalk.yellowBright(path)}] compression failed. ${obj.msg}`, status: 'fail'}); + } + const data = await this.downloadImg(obj.output.url); + // 写回到原来资源中 + assets[path] = new RawSource(Buffer.alloc(data.length, data, 'binary')) const oldSize = Chalk.redBright(ByteSize(obj.input.size)); const newSize = Chalk.greenBright(ByteSize(obj.output.size)); const ratio = Chalk.blueBright(RoundNum(1 - obj.output.ratio, 2, true)); - const dpath = assets[path].existsAt; const msg = `${Figures.tick} Compressed [${Chalk.yellowBright(path)}] completed: Old Size ${oldSize}, New Size ${newSize}, Optimization Ratio ${ratio}`; - Fs.writeFileSync(dpath, data, "binary"); - return Promise.resolve(msg); + return Promise.resolve({msg, status: 'success'}); } catch (err) { const msg = `${Figures.cross} Compressed [${Chalk.yellowBright(path)}] failed: ${Chalk.redBright(err)}`; - return Promise.resolve(msg); + return Promise.resolve({msg, status: 'fail'}); } } downloadImg(url) { @@ -63,8 +73,12 @@ module.exports = class TinyimgWebpackPlugin { const opts = RandomHeader(); return new Promise((resolve, reject) => { const req = Https.request(opts, res => res.on("data", data => { - const obj = JSON.parse(data.toString()); - obj.error ? reject(obj.message) : resolve(obj); + try { + const obj = JSON.parse(data.toString()); + obj.error ? reject({isError: true, msg: obj.message}) : resolve(obj); + } catch (error) { + reject({isError: true, msg: error.message || '图片解析失败'}) + } })); req.write(file, "binary"); req.on("error", e => reject(e)); diff --git a/test/src/img/pig-3.jpg b/test/src/img/pig-3.jpg deleted file mode 100644 index 223a532..0000000 Binary files a/test/src/img/pig-3.jpg and /dev/null differ diff --git a/test/src/img/pig-3.png b/test/src/img/pig-3.png new file mode 100644 index 0000000..3d308fc Binary files /dev/null and b/test/src/img/pig-3.png differ diff --git a/test/src/index.scss b/test/src/index.scss index f3c4842..00d7bf6 100644 --- a/test/src/index.scss +++ b/test/src/index.scss @@ -18,6 +18,6 @@ background-image: url("./img/pig-2.jpg"); } &-3 { - background-image: url("./img/pig-3.jpg"); + background-image: url("./img/pig-3.png"); } } \ No newline at end of file