Skip to content

Instantly share code, notes, and snippets.

@stefanjudis
Last active October 2, 2019 07:36
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save stefanjudis/3402288b9970d161b5da5f62caf0db66 to your computer and use it in GitHub Desktop.
Save stefanjudis/3402288b9970d161b5da5f62caf0db66 to your computer and use it in GitHub Desktop.
Cached SQIP implementation on Netlify
{
"name": "sqip-cache-tryout",
"version": "1.0.0",
"description": "",
"main": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "stefan judis <stefanjudis@gmail.com>",
"license": "MIT",
"dependencies": {
"contentful": "^6.1.0",
"download": "^7.0.0",
"fs-extra": "^6.0.0",
"sqip": "^0.3.3"
}
}
#!/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()
#!/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