From 2a669586de64cebec6d5e62323859fe5707bf1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Tkaczy=C5=84ski?= Date: Mon, 29 Oct 2018 17:18:05 +0100 Subject: [PATCH] feat: use hashed folder names instead of filenames. closes #6232 (#8808) **Related issue:** #6232 @LeKoArts mentioned two ways of implementing it (one that concatenates `argsDigest` with `contentDigest` and other that uses `contentDigest` as one directory and `argsDigest` as another child so images are grouped together and it limits the number of directories in `static` directory). This PR implements the latter. ### Performance impact I measured the performance of original solution and one from this PR 5 times (and ignoring first build after changing gatsby version) for each (every time cleaning the cache) by running `gatsby build` on example [using-gatsby-image](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-gatsby-image). Tested on Linux, Ryzen 2700X and 970 EVO. #### Original (`2.0.18`) - `14.70` - `14.08` - `13.65` - `14.22` - `13.80` **Average:** `14.09` #### This PR: - `13.77` - `13.51` - `13.61` - `13.78` - `13.66` **Average:** `13,666` So this results in 3% improvement in build times (it might be just luck, but at least it doesn't increase build time). --- packages/gatsby-plugin-sharp/package.json | 1 + .../src/__tests__/__snapshots__/index.js.snap | 22 +++++++++---------- .../src/__tests__/index.js | 7 ++++-- packages/gatsby-plugin-sharp/src/index.js | 19 +++++++++++----- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/packages/gatsby-plugin-sharp/package.json b/packages/gatsby-plugin-sharp/package.json index 9e4c9f81076e2..d3438d5212284 100644 --- a/packages/gatsby-plugin-sharp/package.json +++ b/packages/gatsby-plugin-sharp/package.json @@ -11,6 +11,7 @@ "async": "^2.1.2", "bluebird": "^3.5.0", "fs-exists-cached": "^1.0.0", + "fs-extra": "^7.0.0", "imagemin": "^6.0.0", "imagemin-mozjpeg": "^7.0.0", "imagemin-pngquant": "^6.0.0", diff --git a/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap index a72e560cdd9fc..cf718fe9ec64d 100644 --- a/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap @@ -15,14 +15,14 @@ Object { "aspectRatio": 2.0661764705882355, "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAABYlAAAWJQFJUiTwAAABAklEQVQoz61R7WrCQBDM+7+Cv1qhlIogoUWMoH8KrfgOLVXRKDV4d7kkl6/pbsxpqBIo9mBuZ7N3k51bB7TKsrwZVsexyS2rKerwFhYFVI1DnkMQOHIuCaLB+ayuwXlMaApXgvMoxjTU8MIQE4rMx8SnNffUkU/qM/bbiPAeRfgw5n8tB+QgO1kmUvwROdm0kYHmUNoe+NoU2wZTdVjQH7Isg9YRpFIXor8vpGmKjb/FQQgslit8fi3wvQ/OHXLhxRvDHY7Qd5+x3e2udmNzTUN4fZvhoddH566L+8cn9AZuVcvpLR3e9kEAISWEkDAmbRXkGCcJ1r4PRRNPEkPu9Kn2Azs0CqJYU3JKAAAAAElFTkSuQmCC", "density": 144, - "originalImg": "/static/test-1234-e2565.png", + "originalImg": "/static/1234/e2565/test.png", "originalName": undefined, "presentationHeight": 68, "presentationWidth": 141, "sizes": "(max-width: 141px) 100vw, 141px", - "src": "/static/test-1234-e2565.png", - "srcSet": "/static/test-1234-0b382.png 200w, -/static/test-1234-e2565.png 281w", + "src": "/static/1234/e2565/test.png", + "srcSet": "/static/1234/0b382/test.png 200w, +/static/1234/e2565/test.png 281w", "srcSetType": "image/png", } `; @@ -32,14 +32,14 @@ Object { "aspectRatio": 2.0661764705882355, "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAABYlAAAWJQFJUiTwAAABAklEQVQoz61R7WrCQBDM+7+Cv1qhlIogoUWMoH8KrfgOLVXRKDV4d7kkl6/pbsxpqBIo9mBuZ7N3k51bB7TKsrwZVsexyS2rKerwFhYFVI1DnkMQOHIuCaLB+ayuwXlMaApXgvMoxjTU8MIQE4rMx8SnNffUkU/qM/bbiPAeRfgw5n8tB+QgO1kmUvwROdm0kYHmUNoe+NoU2wZTdVjQH7Isg9YRpFIXor8vpGmKjb/FQQgslit8fi3wvQ/OHXLhxRvDHY7Qd5+x3e2udmNzTUN4fZvhoddH566L+8cn9AZuVcvpLR3e9kEAISWEkDAmbRXkGCcJ1r4PRRNPEkPu9Kn2Azs0CqJYU3JKAAAAAElFTkSuQmCC", "density": 144, - "originalImg": "/static/test-1234-76aa7.png", + "originalImg": "/static/1234/76aa7/test.png", "originalName": undefined, "presentationHeight": 136, "presentationWidth": 281, "sizes": "(max-width: 281px) 100vw, 281px", - "src": "/static/test-1234-76aa7.png", - "srcSet": "/static/test-1234-304a5.png 200w, -/static/test-1234-76aa7.png 281w", + "src": "/static/1234/76aa7/test.png", + "srcSet": "/static/1234/304a5/test.png 200w, +/static/1234/76aa7/test.png 281w", "srcSetType": "image/png", } `; @@ -49,13 +49,13 @@ Object { "aspectRatio": 1, "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGElEQVQ4y2P4TwFgGNU8qnlU86jmgdUMAOBEq42KgAyMAAAAAElFTkSuQmCC", "density": 72, - "originalImg": "/static/test-1234-7bb67.png", + "originalImg": "/static/1234/7bb67/test.png", "originalName": undefined, "presentationHeight": 1, "presentationWidth": 1, "sizes": "(max-width: 1px) 100vw, 1px", - "src": "/static/test-1234-7bb67.png", - "srcSet": "/static/test-1234-7bb67.png 1w", + "src": "/static/1234/7bb67/test.png", + "srcSet": "/static/1234/7bb67/test.png 1w", "srcSetType": "image/png", } `; diff --git a/packages/gatsby-plugin-sharp/src/__tests__/index.js b/packages/gatsby-plugin-sharp/src/__tests__/index.js index 8bc762437deea..0be8444a8bc29 100644 --- a/packages/gatsby-plugin-sharp/src/__tests__/index.js +++ b/packages/gatsby-plugin-sharp/src/__tests__/index.js @@ -1,4 +1,5 @@ const path = require(`path`) +const fs = require(`fs-extra`) jest.mock(`async/queue`, () => () => { return { @@ -6,6 +7,8 @@ jest.mock(`async/queue`, () => () => { } }) +fs.ensureDirSync = jest.fn() + const { base64, fluid, @@ -69,8 +72,8 @@ describe(`gatsby-plugin-sharp`, () => { file, }) - expect(result.src.indexOf(file.name)).toBe(8) - expect(result.srcSet.indexOf(file.name)).toBe(8) + expect(path.parse(result.src).name).toBe(file.name) + expect(path.parse(result.srcSet).name).toBe(file.name) }) it(`accounts for pixel density`, async () => { diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 88b899e23263a..89928e26aaa89 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -3,7 +3,7 @@ const crypto = require(`crypto`) const imageSize = require(`probe-image-size`) const _ = require(`lodash`) const Promise = require(`bluebird`) -const fs = require(`fs`) +const fs = require(`fs-extra`) const ProgressBar = require(`progress`) const imagemin = require(`imagemin`) const imageminMozjpeg = require(`imagemin-mozjpeg`) @@ -369,10 +369,16 @@ function queueImageResizing({ file, args = {}, reporter }) { const argsDigestShort = argsDigest.substr(argsDigest.length - 5) - const imgSrc = `/${file.name}-${ - file.internal.contentDigest - }-${argsDigestShort}.${fileExtension}` - const filePath = path.join(process.cwd(), `public`, `static`, imgSrc) + const imgSrc = `/${file.name}.${fileExtension}` + const dirPath = path.join( + process.cwd(), + `public`, + `static`, + file.internal.contentDigest, + argsDigestShort + ) + const filePath = path.join(dirPath, imgSrc) + fs.ensureDirSync(dirPath) // Create function to call when the image is finished. let outsideResolve, outsideReject @@ -421,7 +427,8 @@ function queueImageResizing({ file, args = {}, reporter }) { queueJob(job, reporter) // Prefix the image src. - const prefixedSrc = options.pathPrefix + `/static` + imgSrc + const digestDirPrefix = `${file.internal.contentDigest}/${argsDigestShort}` + const prefixedSrc = options.pathPrefix + `/static/${digestDirPrefix}` + imgSrc return { src: prefixedSrc,