UNPKG

kraken-loader

Version:

Kraken.io image optimisation loader for Webpack 2+

134 lines (110 loc) 2.96 kB
/* eslint no-console: off, consistent-return: off */ const chalk = require('chalk'); const fetch = require('node-fetch'); const utils = require('loader-utils'); const Kraken = require('kraken'); const prettyBytes = require('pretty-bytes'); /** * Default options * * @type {Object} */ const defaults = { enabled: true, secret: null, silent: false, lossy: true, key: null }; /** * Kraken.io API options * * @type {Object} */ let options = {}; /** * Indicate error state * * @type {Boolean} */ let stateOk = true; /** * Print a message to stdout * * @param {String} str - Message string to print to stdout * @param {Boolean} isError - Is the message an error message - will adjust formatting? */ /* eslint no-confusing-arrow: off */ const printMessage = (str, isError = false) => isError ? `${chalk.red('✗')} kraken-loader: ${chalk.grey(`'${str}'`)}` : `${chalk.green('✔')} kraken-loader: ${chalk.grey(`'${str}'`)}`; /** * Main loader function. * * @param {Buffer} source */ const krakenLoader = function (source) { const callback = this.async(); if (this.cacheable) { this.cacheable(); } options = Object.assign( {}, defaults, utils.getOptions(this) ); if ( ! options.enabled || ! stateOk) { return callback(null, source); } // Try loading API credentials from env. vars if ( ! options.key || ! options.secret) { options = Object.assign({}, options, { key: process.env.KRAKEN_LOADER_KEY, secret: process.env.KRAKEN_LOADER_SECRET }); } if ( ! options.key || ! options.secret) { stateOk = false; // prevent duplicate errors return callback(new Error('Missing Kraken API key and secret'), source); } const filename = this.resourcePath.replace(this.context, ''); const kraken = new Kraken({ api_secret: options.secret, api_key: options.key }); // Process file kraken.upload({ lossy: options.lossy, file: this.resourcePath, wait: true }, async (data) => { if ( ! data.success) { const err = new Error(data.message || 'Unknown Kraken API error. Please try again.'); return callback(err, source); } // display savings if ( ! options.silent) { const savings = data.saved_bytes; const origSize = data.original_size; const percent = ((savings / origSize) * 100).toFixed(2); const msg = savings > 0 ? `saved ${prettyBytes(savings)} (${percent}%)` : 'already optimized'; console.log(printMessage(`${filename} - ${msg}`)); } // // Get the optimised file + pass onwards // try { const resp = await fetch(data.kraked_url); const buffer = await resp.buffer(); return callback(null, buffer); } catch (err) { return callback(err, source); } }); }; module.exports = krakenLoader; // Ensure the image isn't UTF-8 encoded; // instead receive the raw buffer module.exports.raw = true;