Last active
October 2, 2019 07:36
-
-
Save stefanjudis/3402288b9970d161b5da5f62caf0db66 to your computer and use it in GitHub Desktop.
Cached SQIP implementation on Netlify
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "sqip-cache-tryout", | |
"version": "1.0.0", | |
"description": "", | |
"main": "", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"keywords": [], | |
"author": "stefan judis <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
"contentful": "^6.1.0", | |
"download": "^7.0.0", | |
"fs-extra": "^6.0.0", | |
"sqip": "^0.3.3" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const contentful = require('contentful') | |
const client = contentful.createClient({ | |
accessToken: '8c6d9bb62a89a05e4f88af2784a0a3f8bcacc7b401084d50f577dfc5f6df0c61', | |
host: 'cdn.contentful.com', | |
space: 'fbr4i5aajb0w' | |
}) | |
const download = require('download') | |
const path = require('path') | |
const {emptyDir, writeFile, readFile} = require('fs-extra') | |
const isProduction = process.env.NODE_ENV === 'production' | |
const SQIP_CACHE = isProduction | |
? path.join('/', 'opt', 'build', 'cache', 'sqip') | |
: path.resolve(__dirname, '.sqip') | |
const JS_DESTINATION = path.resolve(__dirname, 'image-map.js') | |
const sqip = require('sqip') | |
async function sqipItems () { | |
console.log('// --------------------------------------------') | |
if (process.env.WEBHOOK_TITLE === 'CLEAR_CUSTOM_CACHE') { | |
console.log(`Clearing ${SQIP_CACHE}`) | |
await emptyDir(SQIP_CACHE) | |
} | |
console.log('// --------------------------------------------') | |
console.log('Getting asset information') | |
const {items} = await client.getAssets({limit: 1000}) | |
let images = items | |
.filter( | |
({fields}) => fields.file && ['image/png', 'image/jpeg'].indexOf(fields.file.contentType) !== -1 | |
) | |
.map(({sys, fields}) => ({ | |
id: sys.id, | |
revision: sys.revision, | |
url: fields.file.url, | |
filename: `${sys.id}-${sys.revision}.${fields.file.contentType.split('/')[1]}`, | |
svg: null | |
})) | |
console.log('Asset information queried') | |
console.log('// --------------------------------------------') | |
console.log(`Reading cached SVGs from at ${SQIP_CACHE}`) | |
images = await Promise.all(images.map(async (image) => { | |
try { | |
const svg = await readFile(`${SQIP_CACHE}/${image.id}-${image.revision}.svg`, 'utf8') | |
if (svg.startsWith('<svg')) { | |
image.svg = svg | |
} | |
} catch (e) {} | |
return image | |
})) | |
console.log('Cached SVGs read') | |
console.log('// --------------------------------------------') | |
console.log('Downloading images for missing SVGs...') | |
await Promise.all( | |
images.map(({url, filename, svg}) => { | |
if (!svg) { | |
console.log(`${filename} is missing -> downloading`) | |
return download( | |
url.replace(/\/\//, 'https://'), | |
SQIP_CACHE, | |
{ filename } | |
) | |
} | |
return Promise.resolve() | |
}) | |
) | |
console.log('Images downloaded') | |
console.log('// --------------------------------------------') | |
console.log('Creating missing SVGs...') | |
await Promise.all(images.map(({id, revision, filename, svg}) => { | |
if (!svg) { | |
const {final_svg} = sqip({ | |
filename: path.join(SQIP_CACHE, filename), | |
numberOfPrimitives: 10, | |
mode: 0, | |
blur: 0 | |
}) | |
return writeFile( | |
path.join(SQIP_CACHE, `${id}-${revision}.svg`), | |
final_svg | |
) | |
} | |
return Promise.resolve() | |
})) | |
console.log('SVGs created') | |
console.log('// --------------------------------------------') | |
console.log('Reading missing SVGs...') | |
images = await Promise.all(images.map(async (image) => { | |
if (!image.svg) { | |
const svg = await readFile(path.join(SQIP_CACHE, `${image.id}-${image.revision}.svg`), 'utf8') | |
image.svg = svg.replace('<svg', `<svg id="${image.id}"`) | |
} | |
return image | |
})) | |
console.log('SVGs read') | |
console.log('// --------------------------------------------') | |
console.log('Writing JS mapping file') | |
await writeFile( | |
JS_DESTINATION, | |
`export default {\n ${images.map(({id, svg}) => `'${id}': '${svg}'`).join(', ')}\n}\n` | |
) | |
console.log('JS file written') | |
console.log('// --------------------------------------------') | |
} | |
sqipItems() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const contentful = require('contentful') | |
const client = contentful.createClient({ | |
accessToken: '8c6d9bb62a89a05e4f88af2784a0a3f8bcacc7b401084d50f577dfc5f6df0c61', | |
host: 'cdn.contentful.com', | |
space: 'fbr4i5aajb0w' | |
}) | |
const download = require('download') | |
const path = require('path') | |
const {writeFile, readFile} = require('fs-extra') | |
const sqip = require('sqip') | |
const IMAGE_FOLDER = path.resolve(__dirname, '.sqip-without-cache') | |
const JS_DESTINATION = path.resolve(__dirname, 'image-map.js') | |
async function sqipItems () { | |
console.log('Getting asset information') | |
const {items} = await client.getAssets({limit: 1000}) | |
let images = items | |
.filter( | |
({fields}) => fields.file && ['image/png', 'image/jpeg'].indexOf(fields.file.contentType) !== -1 | |
) | |
.map(({sys, fields}) => ({ | |
id: sys.id, | |
revision: sys.revision, | |
url: fields.file.url, | |
filename: `${sys.id}-${sys.revision}.${fields.file.contentType.split('/')[1]}`, | |
svg: null | |
})) | |
console.log(`Asset information queried - ${images.length} assets`) | |
console.log('// --------------------------------------------') | |
console.log('Downloading images for SVGs...') | |
await Promise.all( | |
images.map(({url, filename, svg}) => { | |
return download( | |
url.replace(/\/\//, 'https://'), | |
IMAGE_FOLDER, | |
{ filename } | |
) | |
}) | |
) | |
console.log('Images downloaded') | |
console.log('// --------------------------------------------') | |
console.log('Creating SVGs...') | |
await Promise.all(images.map(({id, revision, filename}) => { | |
const {final_svg} = sqip({ | |
filename: path.join(IMAGE_FOLDER, filename), | |
numberOfPrimitives: 10, | |
mode: 0, | |
blur: 0 | |
}) | |
return writeFile( | |
path.join(IMAGE_FOLDER, `${id}-${revision}.svg`), | |
final_svg | |
) | |
})) | |
console.log('SVGs created') | |
console.log('// --------------------------------------------') | |
console.log('Reading SVGs...') | |
images = await Promise.all(images.map(async (image) => { | |
const svg = await readFile(path.join(IMAGE_FOLDER, `${image.id}-${image.revision}.svg`), 'utf8') | |
image.svg = svg.replace('<svg', `<svg id="${image.id}"`) | |
return image | |
})) | |
console.log('SVGs read') | |
console.log('// --------------------------------------------') | |
console.log('Writing JS mapping file') | |
writeFile( | |
JS_DESTINATION, | |
`export default {\n ${images.map(({id, svg}) => `'${id}': '${svg}'`).join(', ')}\n}\n` | |
) | |
console.log('JS file written') | |
console.log('// --------------------------------------------') | |
} | |
sqipItems() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment