From 5865ef132859eea344404cf17311c7043cae2568 Mon Sep 17 00:00:00 2001 From: polarathene Date: Sun, 30 Dec 2018 16:32:10 +0800 Subject: [PATCH 01/10] feat(gatsby-plugin-sharp): Configurable base64 width Allows for using larger(or smaller) than the default `20px` width, trading size for quality via more/less pixels. Adds the `base64Width` arg to the fixed & fluid nodes. --- packages/gatsby-plugin-sharp/src/index.js | 4 +++- packages/gatsby-transformer-sharp/src/extend-node-type.js | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 62b74f04f4442..4e8610dc57d1a 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -672,7 +672,7 @@ async function fluid({ file, args = {}, reporter, cache }) { }) }) - const base64Width = 20 + const base64Width = options.base64Width || 20 const base64Height = Math.max(1, Math.round((base64Width * height) / width)) const base64Args = { duotone: options.duotone, @@ -787,6 +787,8 @@ async function fixed({ file, args = {}, reporter, cache }) { }) const base64Args = { + // height is adjusted accordingly with respect to the aspect ratio + width: options.base64Width, duotone: options.duotone, grayscale: options.grayscale, rotate: options.rotate, diff --git a/packages/gatsby-transformer-sharp/src/extend-node-type.js b/packages/gatsby-transformer-sharp/src/extend-node-type.js index 09e5c70e9e297..4b1f23cbec6bd 100644 --- a/packages/gatsby-transformer-sharp/src/extend-node-type.js +++ b/packages/gatsby-transformer-sharp/src/extend-node-type.js @@ -115,6 +115,9 @@ const fixedNodeType = ({ height: { type: GraphQLInt, }, + base64Width: { + type: GraphQLInt, + }, jpegProgressive: { type: GraphQLBoolean, defaultValue: true, @@ -241,6 +244,9 @@ const fluidNodeType = ({ maxHeight: { type: GraphQLInt, }, + base64Width: { + type: GraphQLInt, + }, grayscale: { type: GraphQLBoolean, defaultValue: false, From 241c2f6a47b4c1597d720eba08d787a24c67732d Mon Sep 17 00:00:00 2001 From: polarathene Date: Sun, 30 Dec 2018 16:47:44 +0800 Subject: [PATCH 02/10] chore(gatsby-plugin-sharp): Remove magic numbers Provides added clarity for where these numbers are used. Especially for the value of `72` where it's not clear if the value was for image or display density. `defaultBase64Width` improves clarity and keeps it DRY across both usages. --- packages/gatsby-plugin-sharp/src/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 4e8610dc57d1a..3d285c968f5fc 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -475,8 +475,9 @@ function queueImageResizing({ file, args = {}, reporter }) { } } +const defaultBase64Width = 20 // A value in pixels(Int) async function generateBase64({ file, args, reporter }) { - const options = healOptions(args, { width: 20 }) + const options = healOptions(args, { width: defaultBase64Width }) let pipeline try { pipeline = sharp(file.absolutePath).rotate() @@ -570,9 +571,10 @@ async function fluid({ file, args = {}, reporter, cache }) { } const { width, height, density, format } = metadata + const density_72PPI = 72 // Standard digital image pixel density const pixelRatio = options.sizeByPixelDensity && typeof density === `number` && density > 0 - ? density / 72 + ? density / density_72PPI : 1 // if no maxWidth is passed, we need to resize the image based on the passed maxHeight @@ -672,7 +674,7 @@ async function fluid({ file, args = {}, reporter, cache }) { }) }) - const base64Width = options.base64Width || 20 + const base64Width = options.base64Width || defaultBase64Width const base64Height = Math.max(1, Math.round((base64Width * height) / width)) const base64Args = { duotone: options.duotone, From 34bc96213483f6cb614f257d28d4b36d9870088c Mon Sep 17 00:00:00 2001 From: polarathene Date: Tue, 1 Jan 2019 14:06:07 +0800 Subject: [PATCH 03/10] fix(gatsby-image): Support placeholder image with backgroundColor Place the `backgroundColor` div before/behind the placeholder img. --- packages/gatsby-image/src/index.js | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/gatsby-image/src/index.js b/packages/gatsby-image/src/index.js index b8c37a15e5ab7..841bf27471fdc 100644 --- a/packages/gatsby-image/src/index.js +++ b/packages/gatsby-image/src/index.js @@ -275,16 +275,6 @@ class Image extends React.Component { }} /> - {/* Show the blurry base64 image. */} - {image.base64 && ( - - )} - - {/* Show the traced SVG image. */} - {image.tracedSVG && ( - - )} - {/* Show a solid background color. */} {bgColor && ( )} + {/* Show the blurry base64 image. */} + {image.base64 && ( + + )} + + {/* Show the traced SVG image. */} + {image.tracedSVG && ( + + )} + {/* Once the image is visible (or the browser doesn't support IntersectionObserver), start downloading the image */} {this.state.isVisible && ( @@ -361,16 +361,6 @@ class Image extends React.Component { ref={this.handleRef} key={`fixed-${JSON.stringify(image.srcSet)}`} > - {/* Show the blurry base64 image. */} - {image.base64 && ( - - )} - - {/* Show the traced SVG image. */} - {image.tracedSVG && ( - - )} - {/* Show a solid background color. */} {bgColor && ( )} + {/* Show the blurry base64 image. */} + {image.base64 && ( + + )} + + {/* Show the traced SVG image. */} + {image.tracedSVG && ( + + )} + {/* Once the image is visible, start downloading the image */} {this.state.isVisible && ( From 43c971f1a9983d4eedda30bd384e6136e6b17a7c Mon Sep 17 00:00:00 2001 From: polarathene Date: Tue, 1 Jan 2019 14:10:32 +0800 Subject: [PATCH 04/10] chore(gatsby-image): Share common transitionDelay variable They seem all intended to use the same duration of `0.25s`, `fluid` backgroundColor div actually used `0.35s` for some reason which seemed a possible typo, this corrects that and avoids it in future. --- packages/gatsby-image/src/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/gatsby-image/src/index.js b/packages/gatsby-image/src/index.js index 841bf27471fdc..997f96e289d6a 100644 --- a/packages/gatsby-image/src/index.js +++ b/packages/gatsby-image/src/index.js @@ -232,10 +232,11 @@ class Image extends React.Component { const bgColor = typeof backgroundColor === `boolean` ? `lightgray` : backgroundColor + const initialDelay = `0.25s` const imagePlaceholderStyle = { opacity: this.state.imgLoaded ? 0 : 1, transition: `opacity 0.5s`, - transitionDelay: this.state.imgLoaded ? `0.5s` : `0.25s`, + transitionDelay: this.state.imgLoaded ? `0.5s` : initialDelay, ...imgStyle, ...placeholderStyle, } @@ -285,7 +286,7 @@ class Image extends React.Component { top: 0, bottom: 0, opacity: !this.state.imgLoaded ? 1 : 0, - transitionDelay: `0.35s`, + transitionDelay: initialDelay, right: 0, left: 0, }} @@ -369,7 +370,7 @@ class Image extends React.Component { backgroundColor: bgColor, width: image.width, opacity: !this.state.imgLoaded ? 1 : 0, - transitionDelay: `0.25s`, + transitionDelay: initialDelay, height: image.height, }} /> From b06b9e012510bca014041dad23ba0c170c66c3b6 Mon Sep 17 00:00:00 2001 From: polarathene Date: Wed, 9 Jan 2019 20:53:38 +0800 Subject: [PATCH 05/10] feat(gatsby-plugin-sharp): Allow base64 format to differ, allow WEBP For example, WEBP base64 placeholders with a `backgroundColor` as fallback while using JPG/PNG with WEBP for the `` element. Adds the `forceBase64Format` config option. Adds support for WEBP base64 images. --- packages/gatsby-plugin-sharp/src/index.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 3d285c968f5fc..54393d923f7f6 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -43,6 +43,7 @@ exports.setBoundActionCreators = actions => { /// Plugin options are loaded onPreInit in gatsby-node const pluginDefaults = { + forceBase64Format: false, useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, stripMetadata: true, } @@ -486,6 +487,10 @@ async function generateBase64({ file, args, reporter }) { return null } + if (pluginOptions.forceBase64Format) { + args.toFormat = pluginOptions.forceBase64Format + } + pipeline .resize(options.width, options.height, { position: options.cropFocus, @@ -500,6 +505,10 @@ async function generateBase64({ file, args, reporter }) { progressive: options.jpegProgressive, force: args.toFormat === `jpg`, }) + .webp({ + quality: options.quality, + force: args.toFormat === `webp`, + }) // grayscale if (options.grayscale) { From c12ec409937dcd75e3263e1dc98ec7e9c142c077 Mon Sep 17 00:00:00 2001 From: polarathene Date: Wed, 9 Jan 2019 23:58:01 +0800 Subject: [PATCH 06/10] chore(gatsby-image): Update test snapshot --- .../src/__tests__/__snapshots__/index.js.snap | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap index 526704fd7850b..9d084789ac8b2 100644 --- a/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap @@ -6,6 +6,10 @@ exports[` should render fixed size images 1`] = ` class="fixedImage gatsby-image-wrapper" style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;" > +
should render fixed size images 1`] = ` style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 1; color: red;" title="Title for the image" /> -
should render fluid images 1`] = `
+
should render fluid images 1`] = ` style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 1; color: red;" title="Title for the image" /> -
Date: Mon, 14 Jan 2019 22:38:19 +0800 Subject: [PATCH 07/10] feat(gatsby-plugin-sharp): Support base64Width as a config option Allows setting a project wide default, rather than having to request it per image. Updates `defaultBase64Width` to be a function as `pluginOptions` has not initialized when assigned. --- packages/gatsby-plugin-sharp/src/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 54393d923f7f6..55802b2f46959 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -476,9 +476,10 @@ function queueImageResizing({ file, args = {}, reporter }) { } } -const defaultBase64Width = 20 // A value in pixels(Int) +// A value in pixels(Int) +const defaultBase64Width = () => pluginOptions.base64Width || 20 async function generateBase64({ file, args, reporter }) { - const options = healOptions(args, { width: defaultBase64Width }) + const options = healOptions(args, { width: defaultBase64Width() }) let pipeline try { pipeline = sharp(file.absolutePath).rotate() @@ -683,7 +684,7 @@ async function fluid({ file, args = {}, reporter, cache }) { }) }) - const base64Width = options.base64Width || defaultBase64Width + const base64Width = options.base64Width || defaultBase64Width() const base64Height = Math.max(1, Math.round((base64Width * height) / width)) const base64Args = { duotone: options.duotone, From 142f48463417eaddce7dff6f246d9cabf43b0ebb Mon Sep 17 00:00:00 2001 From: polarathene Date: Tue, 15 Jan 2019 19:59:31 +0800 Subject: [PATCH 08/10] feat(gatsby-plugin-sharp): Support forceBase64Format as query arg --- packages/gatsby-plugin-sharp/src/index.js | 10 ++++++++-- .../gatsby-transformer-sharp/src/extend-node-type.js | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 55802b2f46959..1a2723730df21 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -93,6 +93,7 @@ const generalArgs = { duotone: false, pathPrefix: ``, toFormat: ``, + toFormatBase64: ``, sizeByPixelDensity: false, } @@ -102,6 +103,7 @@ const healOptions = (args, defaultArgs) => { options.pngCompressionLevel = parseInt(options.pngCompressionLevel, 10) options.pngCompressionSpeed = parseInt(options.pngCompressionSpeed, 10) options.toFormat = options.toFormat.toLowerCase() + options.toFormatBase64 = options.toFormatBase64.toLowerCase() // only set width to 400 if neither width nor height is passed if (options.width === undefined && options.height === undefined) { @@ -488,8 +490,10 @@ async function generateBase64({ file, args, reporter }) { return null } - if (pluginOptions.forceBase64Format) { - args.toFormat = pluginOptions.forceBase64Format + const forceBase64Format = + args.toFormatBase64 || pluginOptions.forceBase64Format + if (forceBase64Format) { + args.toFormat = forceBase64Format } pipeline @@ -691,6 +695,7 @@ async function fluid({ file, args = {}, reporter, cache }) { grayscale: options.grayscale, rotate: options.rotate, toFormat: options.toFormat, + toFormatBase64: options.toFormatBase64, width: base64Width, height: base64Height, } @@ -805,6 +810,7 @@ async function fixed({ file, args = {}, reporter, cache }) { grayscale: options.grayscale, rotate: options.rotate, toFormat: options.toFormat, + toFormatBase64: options.toFormatBase64, } // Get base64 version diff --git a/packages/gatsby-transformer-sharp/src/extend-node-type.js b/packages/gatsby-transformer-sharp/src/extend-node-type.js index 4b1f23cbec6bd..923101778c18a 100644 --- a/packages/gatsby-transformer-sharp/src/extend-node-type.js +++ b/packages/gatsby-transformer-sharp/src/extend-node-type.js @@ -146,6 +146,10 @@ const fixedNodeType = ({ type: ImageFormatType, defaultValue: ``, }, + toFormatBase64: { + type: ImageFormatType, + defaultValue: ``, + }, cropFocus: { type: ImageCropFocusType, defaultValue: sharp.strategy.attention, @@ -275,6 +279,10 @@ const fluidNodeType = ({ type: ImageFormatType, defaultValue: ``, }, + toFormatBase64: { + type: ImageFormatType, + defaultValue: ``, + }, cropFocus: { type: ImageCropFocusType, defaultValue: sharp.strategy.attention, From ec0071b2abf486cb2251f7fc8ba456774b8acd5b Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Tue, 5 Mar 2019 02:17:22 +1300 Subject: [PATCH 09/10] Change `density_72PPI` to `defaultImagePPI` Co-Authored-By: polarathene --- packages/gatsby-plugin-sharp/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 1a2723730df21..fc5033586839f 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -585,7 +585,7 @@ async function fluid({ file, args = {}, reporter, cache }) { } const { width, height, density, format } = metadata - const density_72PPI = 72 // Standard digital image pixel density + const defaultImagePPI = 72 // Standard digital image pixel density const pixelRatio = options.sizeByPixelDensity && typeof density === `number` && density > 0 ? density / density_72PPI From 7d961daf6086d97ba8db3b3ef91534997d7b2f84 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Tue, 5 Mar 2019 02:18:32 +1300 Subject: [PATCH 10/10] Change `density_72PPI` to `defaultImagePPI` 2 Co-Authored-By: polarathene --- packages/gatsby-plugin-sharp/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index fc5033586839f..955d629da7b7c 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -588,7 +588,7 @@ async function fluid({ file, args = {}, reporter, cache }) { const defaultImagePPI = 72 // Standard digital image pixel density const pixelRatio = options.sizeByPixelDensity && typeof density === `number` && density > 0 - ? density / density_72PPI + ? density / defaultImagePPI : 1 // if no maxWidth is passed, we need to resize the image based on the passed maxHeight