From 10bc67901137503e0286fb5fb3af18e419731332 Mon Sep 17 00:00:00 2001 From: Marcel Fetten Date: Wed, 3 Oct 2018 18:53:17 +0200 Subject: [PATCH] feat: add option to use mozjpeg (#8621) --- packages/gatsby-plugin-sharp/README.md | 13 +++++++ packages/gatsby-plugin-sharp/package.json | 1 + packages/gatsby-plugin-sharp/src/index.js | 44 +++++++++++++++++++---- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/packages/gatsby-plugin-sharp/README.md b/packages/gatsby-plugin-sharp/README.md index 346c74e2de4c0..028cd95089a98 100644 --- a/packages/gatsby-plugin-sharp/README.md +++ b/packages/gatsby-plugin-sharp/README.md @@ -229,6 +229,18 @@ fixed( } ``` +### Using MozJPEG + +You can opt-in to use [MozJPEG][16] for jpeg-encoding. MozJPEG provides even +better image compression than the default encoder used in `gatsby-plugin-sharp`. +However, when using MozJPEG the build time of your Gatsby project will increase +significantly. +To enable MozJPEG set the [environment variable](/docs/environment-variables/#environment-variables): + +```shell +GATSBY_JPEG_ENCODER=MOZJPEG +``` + [1]: https://alistapart.com/article/finessing-fecolormatrix [2]: http://blog.72lions.com/blog/2015/7/7/duotone-in-js [3]: https://ines.io/blog/dynamic-duotone-svg-jade @@ -244,3 +256,4 @@ fixed( [13]: https://github.com/tooolbox/node-potrace#parameters [14]: https://github.com/oliver-moran/jimp [15]: http://sharp.dimens.io/en/stable/api-operation/#flatten +[16]: https://github.com/mozilla/mozjpeg diff --git a/packages/gatsby-plugin-sharp/package.json b/packages/gatsby-plugin-sharp/package.json index 65711cb03b74d..5602c80ad5292 100644 --- a/packages/gatsby-plugin-sharp/package.json +++ b/packages/gatsby-plugin-sharp/package.json @@ -12,6 +12,7 @@ "bluebird": "^3.5.0", "fs-exists-cached": "^1.0.0", "imagemin": "^6.0.0", + "imagemin-mozjpeg": "^7.0.0", "imagemin-pngquant": "^6.0.0", "imagemin-webp": "^4.1.0", "lodash": "^4.17.10", diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 20ba4880837d2..8f5fed6e6ab84 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -6,6 +6,7 @@ const Promise = require(`bluebird`) const fs = require(`fs`) const ProgressBar = require(`progress`) const imagemin = require(`imagemin`) +const imageminMozjpeg = require(`imagemin-mozjpeg`) const imageminPngquant = require(`imagemin-pngquant`) const imageminWebp = require(`imagemin-webp`) const queue = require(`async/queue`) @@ -100,6 +101,8 @@ const healOptions = (args, defaultArgs) => { return options } +const useMozjpeg = process.env.GATSBY_JPEG_ENCODER === `MOZJPEG` + let totalJobs = 0 const processFile = (file, jobs, cb, reporter) => { // console.log("totalJobs", totalJobs) @@ -147,11 +150,6 @@ const processFile = (file, jobs, cb, reporter) => { adaptiveFiltering: false, force: args.toFormat === `png`, }) - .jpeg({ - quality: args.quality, - progressive: args.jpegProgressive, - force: args.toFormat === `jpg`, - }) .webp({ quality: args.quality, force: args.toFormat === `webp`, @@ -161,6 +159,15 @@ const processFile = (file, jobs, cb, reporter) => { force: args.toFormat === `tiff`, }) + // jpeg + if (!useMozjpeg) { + clonedPipeline = clonedPipeline.jpeg({ + quality: args.quality, + progressive: args.jpegProgressive, + force: args.toFormat === `jpg`, + }) + } + // grayscale if (args.grayscale) { clonedPipeline = clonedPipeline.grayscale() @@ -223,6 +230,31 @@ const processFile = (file, jobs, cb, reporter) => { .catch(onFinish) ) .catch(onFinish) + // Compress jpeg + } else if ( + useMozjpeg && + ((job.file.extension === `jpg` && args.toFormat === ``) || + (job.file.extension === `jpeg` && args.toFormat === ``) || + args.toFormat === `jpg`) + ) { + clonedPipeline + .toBuffer() + .then(sharpBuffer => + imagemin + .buffer(sharpBuffer, { + plugins: [ + imageminMozjpeg({ + quality: args.quality, + progressive: args.jpegProgressive, + }), + ], + }) + .then(imageminBuffer => { + fs.writeFile(job.outputPath, imageminBuffer, onFinish) + }) + .catch(onFinish) + ) + .catch(onFinish) // Compress webp } else if ( (job.file.extension === `webp` && args.toFormat === ``) || @@ -241,7 +273,7 @@ const processFile = (file, jobs, cb, reporter) => { .catch(onFinish) ) .catch(onFinish) - // any other format (jpeg, tiff) - don't compress it just handle output + // any other format (tiff) - don't compress it just handle output } else { clonedPipeline.toFile(job.outputPath, onFinish) }