Skip to content

Commit

Permalink
feat(gatsby-plugin-sharp): reduce encoding time and install size (gat…
Browse files Browse the repository at this point in the history
…sbyjs#32851)

* feat(gatsby-plugin-sharp): reduce encoding time and install size

- Upgrade sharp to v0.29.0
- Replace use of imagemin with sharp equivalents
- Reduces JPEG, PNG and AVIF encoding time by up to 50%
- Reduces install size/time by ~10% (~19MB smaller)

* sync sharp version in all packages (#1)

Co-authored-by: Michal Piechowiak <misiek.piechowiak@gmail.com>
  • Loading branch information
lovell and pieh authored Aug 20, 2021
1 parent 1706d8f commit ddcfbd8
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 570 deletions.
2 changes: 1 addition & 1 deletion docs/docs/conceptual/image-plugin-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ The plugin exports a number of other helper functions designed to help end-users

### `gatsby-plugin-sharp`

This includes the actual image processing functions from both sharp but also imagemin and potrace. It includes the functions that generate the image data object, including calculating which srcset sizes to generate. It exports `generateImageData`, which is used by `gatsby-transformer-sharp` and `gatsby-plugin-image`. It takes a `File` node and the image processing arguments, calculates which images to generate, processes these images and returns an image data object suitable for passing to `GatsbyImage`. It also exports helper functions for third party plugins to use, such as `traceSVG`.
This includes the actual image processing functions from sharp and potrace. It includes the functions that generate the image data object, including calculating which srcset sizes to generate. It exports `generateImageData`, which is used by `gatsby-transformer-sharp` and `gatsby-plugin-image`. It takes a `File` node and the image processing arguments, calculates which images to generate, processes these images and returns an image data object suitable for passing to `GatsbyImage`. It also exports helper functions for third party plugins to use, such as `traceSVG`.

### `gatsby-transformer-sharp`

Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby-plugin-manifest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"gatsby-core-utils": "^2.13.0-next.0",
"gatsby-plugin-utils": "^1.13.0-next.0",
"semver": "^7.3.5",
"sharp": "^0.28.3"
"sharp": "^0.29.0"
},
"devDependencies": {
"@babel/cli": "^7.14.8",
Expand Down
5 changes: 1 addition & 4 deletions packages/gatsby-plugin-sharp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@
"gatsby-plugin-utils": "^1.13.0-next.0",
"gatsby-telemetry": "^2.13.0-next.0",
"got": "^10.7.0",
"imagemin": "^7.0.1",
"imagemin-mozjpeg": "^9.0.0",
"imagemin-pngquant": "^9.0.2",
"lodash": "^4.17.21",
"mini-svg-data-uri": "^1.3.3",
"potrace": "^2.1.8",
"probe-image-size": "^6.0.0",
"progress": "^2.0.3",
"semver": "^7.3.4",
"sharp": "^0.28.3",
"sharp": "^0.29.0",
"svgo": "1.3.2",
"uuid": "3.4.0"
},
Expand Down
61 changes: 3 additions & 58 deletions packages/gatsby-plugin-sharp/src/process-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ const fs = require(`fs-extra`)
const path = require(`path`)
const debug = require(`debug`)(`gatsby:gatsby-plugin-sharp`)
const duotone = require(`./duotone`)
const imagemin = require(`imagemin`)
const imageminMozjpeg = require(`imagemin-mozjpeg`)
const imageminPngquant = require(`imagemin-pngquant`)
const { healOptions } = require(`./plugin-options`)
const { SharpError } = require(`./sharp-error`)
const { createContentDigest } = require(`gatsby-core-utils`)
Expand Down Expand Up @@ -113,6 +110,7 @@ exports.processFile = (file, transforms, options = {}) => {
.png({
compressionLevel: transformArgs.pngCompressionLevel,
adaptiveFiltering: false,
quality: transformArgs.pngQuality || transformArgs.quality,
force: transformArgs.toFormat === `png`,
})
.webp({
Expand All @@ -127,15 +125,12 @@ exports.processFile = (file, transforms, options = {}) => {
quality: transformArgs.quality,
force: transformArgs.toFormat === `avif`,
})

// jpeg
if (!options.useMozJpeg) {
clonedPipeline = clonedPipeline.jpeg({
.jpeg({
mozjpeg: options.useMozJpeg,
quality: transformArgs.jpegQuality || transformArgs.quality,
progressive: transformArgs.jpegProgressive,
force: transformArgs.toFormat === `jpg`,
})
}

// grayscale
if (transformArgs.grayscale) {
Expand All @@ -156,22 +151,6 @@ exports.processFile = (file, transforms, options = {}) => {
)
}

// lets decide how we want to save this transform
if (transformArgs.toFormat === `png`) {
await compressPng(clonedPipeline, outputPath, {
pngQuality: transformArgs.pngQuality,
quality: transformArgs.quality,
pngCompressionSpeed: transformArgs.compressionSpeed,
stripMetadata: options.stripMetadata,
})
return transform
}

if (options.useMozJpeg && transformArgs.toFormat === `jpg`) {
await compressJpg(clonedPipeline, outputPath, transformArgs)
return transform
}

try {
await clonedPipeline.toFile(outputPath)
} catch (err) {
Expand All @@ -192,40 +171,6 @@ exports.processFile = (file, transforms, options = {}) => {
})
}

const compressPng = (pipeline, outputPath, options) =>
pipeline.toBuffer().then(sharpBuffer =>
imagemin
.buffer(sharpBuffer, {
plugins: [
imageminPngquant({
quality: [
(options.pngQuality || options.quality) / 100,
Math.min(((options.pngQuality || options.quality) + 25) / 100, 1),
], // e.g. [0.4, 0.65]
speed: options.pngCompressionSpeed
? options.pngCompressionSpeed
: undefined,
strip: !!options.stripMetadata, // Must be a bool
}),
],
})
.then(imageminBuffer => fs.writeFile(outputPath, imageminBuffer))
)

const compressJpg = (pipeline, outputPath, options) =>
pipeline.toBuffer().then(sharpBuffer =>
imagemin
.buffer(sharpBuffer, {
plugins: [
imageminMozjpeg({
quality: options.jpegQuality || options.quality,
progressive: options.jpegProgressive,
}),
],
})
.then(imageminBuffer => fs.writeFile(outputPath, imageminBuffer))
)

exports.createArgsDigest = args => {
const argsDigest = createContentDigest(args)

Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby-remark-images-contentful/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"is-relative-url": "^3.0.0",
"lodash": "^4.17.21",
"semver": "^7.3.2",
"sharp": "^0.28.3",
"sharp": "^0.29.0",
"unist-util-select": "^3.0.4"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby-source-shopify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"gatsby-core-utils": "^2.13.0-next.0",
"gatsby-source-filesystem": "^3.13.0-next.0",
"node-fetch": "^2.6.1",
"sharp": "^0.28.3",
"sharp": "^0.29.0",
"shift-left": "^0.1.5"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/gatsby-transformer-sharp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"potrace": "^2.1.8",
"probe-image-size": "^6.0.0",
"semver": "^7.3.5",
"sharp": "^0.28.3"
"sharp": "^0.29.0"
},
"devDependencies": {
"@babel/cli": "^7.14.8",
Expand Down
Loading

0 comments on commit ddcfbd8

Please sign in to comment.