Skip to content

Commit e6d9eb3

Browse files
LekoArtspieh
andauthored
feat(gatsby-plugin-sharp): Use file streams instead of file paths (#33029)
* copied changes * new changes * fix(sharp): retain order of operations and images * use toBuffer and writeFile instead write stream (at least for now) * revert making queueImageResizing async * fixing up too much of revert in previous commit Co-authored-by: Michal Piechowiak <[email protected]>
1 parent 5d5ad48 commit e6d9eb3

File tree

6 files changed

+45
-13
lines changed

6 files changed

+45
-13
lines changed

packages/gatsby-plugin-sharp/src/__tests__/trace-svg.js

+17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ jest.mock(`sharp`, () => {
66
png: () => pipeline,
77
jpeg: () => pipeline,
88
toFile: (_, cb) => cb(),
9+
on: () => pipeline,
10+
once: () => pipeline,
11+
write: () => pipeline,
12+
end: () => pipeline,
13+
emit: () => pipeline,
914
}
1015
return pipeline
1116
}
@@ -16,6 +21,18 @@ jest.mock(`sharp`, () => {
1621
return sharp
1722
})
1823

24+
jest.mock(`fs-extra`, () => {
25+
return {
26+
...jest.requireActual(`fs-extra`),
27+
createReadStream: () => {
28+
const stream = {
29+
pipe: () => stream,
30+
}
31+
return stream
32+
},
33+
}
34+
})
35+
1936
jest.mock(`potrace`, () => {
2037
const circleSvgString = `<svg height="100" width="100"><circle cx="50" cy="50" r="40" /></svg>`
2138
return {

packages/gatsby-plugin-sharp/src/image-data.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { IGatsbyImageData, ISharpGatsbyImageArgs } from "gatsby-plugin-image"
33
import { GatsbyCache, Node } from "gatsby"
44
import { Reporter } from "gatsby/reporter"
5+
import fs from "fs-extra"
56
import { rgbToHex, calculateImageSizes, getSrcSet, getSizes } from "./utils"
67
import { traceSVG, getImageSizeAsync, base64, batchQueueImageResizing } from "."
78
import sharp from "./safe-sharp"
@@ -15,7 +16,7 @@ const DEFAULT_BREAKPOINTS = [750, 1080, 1366, 1920]
1516
type ImageFormat = "jpg" | "png" | "webp" | "avif" | "" | "auto"
1617

1718
export type FileNode = Node & {
18-
absolutePath?: string
19+
absolutePath: string
1920
extension: string
2021
}
2122

@@ -44,7 +45,9 @@ export async function getImageMetadata(
4445
}
4546

4647
try {
47-
const pipeline = sharp(file.absolutePath)
48+
const pipeline = sharp()
49+
50+
fs.createReadStream(file.absolutePath).pipe(pipeline)
4851

4952
const { width, height, density, format } = await pipeline.metadata()
5053

packages/gatsby-plugin-sharp/src/index.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,12 @@ async function generateBase64({ file, args = {}, reporter }) {
267267
})
268268
let pipeline
269269
try {
270-
pipeline = !options.failOnError
271-
? sharp(file.absolutePath, { failOnError: false })
272-
: sharp(file.absolutePath)
270+
pipeline = !options.failOnError ? sharp({ failOnError: false }) : sharp()
273271

274272
if (!options.rotate) {
275273
pipeline.rotate()
276274
}
275+
fs.createReadStream(file.absolutePath).pipe(pipeline)
277276
} catch (err) {
278277
reportError(`Failed to process image ${file.absolutePath}`, err, reporter)
279278
return null
@@ -413,7 +412,10 @@ async function getTracedSVG({ file, options, cache, reporter }) {
413412
async function stats({ file, reporter }) {
414413
let imgStats
415414
try {
416-
imgStats = await sharp(file.absolutePath).stats()
415+
const pipeline = sharp()
416+
fs.createReadStream(file.absolutePath).pipe(pipeline)
417+
418+
imgStats = await pipeline.stats()
417419
} catch (err) {
418420
reportError(
419421
`Failed to get stats for image ${file.absolutePath}`,
@@ -450,7 +452,10 @@ async function fluid({ file, args = {}, reporter, cache }) {
450452
// images are intended to be displayed at their native resolution.
451453
let metadata
452454
try {
453-
metadata = await sharp(file.absolutePath).metadata()
455+
const pipeline = sharp()
456+
fs.createReadStream(file.absolutePath).pipe(pipeline)
457+
458+
metadata = await pipeline.metadata()
454459
} catch (err) {
455460
reportError(
456461
`Failed to retrieve metadata from image ${file.absolutePath}`,

packages/gatsby-plugin-sharp/src/process-file.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ sharp.concurrency(1)
5656
exports.processFile = (file, transforms, options = {}) => {
5757
let pipeline
5858
try {
59-
pipeline = !options.failOnError
60-
? sharp(file, { failOnError: false })
61-
: sharp(file)
59+
pipeline = !options.failOnError ? sharp({ failOnError: false }) : sharp()
6260

6361
// Keep Metadata
6462
if (!options.stripMetadata) {
6563
pipeline = pipeline.withMetadata()
6664
}
65+
fs.createReadStream(file).pipe(pipeline)
6766
} catch (err) {
6867
throw new SharpError(`Failed to load image ${file} into sharp.`, err)
6968
}
@@ -152,7 +151,8 @@ exports.processFile = (file, transforms, options = {}) => {
152151
}
153152

154153
try {
155-
await clonedPipeline.toFile(outputPath)
154+
const buffer = await clonedPipeline.toBuffer()
155+
await fs.writeFile(outputPath, buffer)
156156
} catch (err) {
157157
throw new Error(
158158
`Failed to write ${file} into ${outputPath}. (${err.message})`

packages/gatsby-plugin-sharp/src/trace-svg.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { promisify } = require(`bluebird`)
2+
const fs = require(`fs-extra`)
23
const _ = require(`lodash`)
34
const tmpDir = require(`os`).tmpdir()
45
const path = require(`path`)
@@ -17,11 +18,12 @@ exports.notMemoizedPrepareTraceSVGInputFile = async ({
1718
}) => {
1819
let pipeline
1920
try {
20-
pipeline = sharp(file.absolutePath)
21+
pipeline = sharp()
2122

2223
if (!options.rotate) {
2324
pipeline.rotate()
2425
}
26+
fs.createReadStream(file.absolutePath).pipe(pipeline)
2527
} catch (err) {
2628
reportError(`Failed to process image ${file.absolutePath}`, err, reporter)
2729
return

packages/gatsby-plugin-sharp/src/utils.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sharp from "./safe-sharp"
2+
import fs from "fs-extra"
23

34
export function rgbToHex(red, green, blue) {
45
return `#${(blue | (green << 8) | (red << 16) | (1 << 24))
@@ -39,6 +40,7 @@ export function calculateImageSizes(args) {
3940
return []
4041
}
4142
}
43+
4244
export function fixedImageSizes({
4345
file,
4446
imgDimensions,
@@ -288,7 +290,10 @@ export const getDominantColor = async absolutePath => {
288290
return dominantColor
289291
}
290292

291-
const pipeline = sharp(absolutePath)
293+
const pipeline = sharp()
294+
295+
fs.createReadStream(absolutePath).pipe(pipeline)
296+
292297
const { dominant } = await pipeline.stats()
293298

294299
// Fallback in case sharp doesn't support dominant

0 commit comments

Comments
 (0)