1
0
mirror of synced 2025-12-19 18:10:59 -05:00
Files
docs/lib/render-content/plugins/rewrite-asset-urls.js
Peter Bengtsson ae3dadfc66 cache asset images more aggressively (#23553)
* cache asset images more aggressively

* more careful about which gets the manual surrogate key

* fix rendered-content-link-checker script too

* feedbacked
2021-12-10 13:01:48 +00:00

53 lines
1.8 KiB
JavaScript

import fs from 'fs'
import { visit } from 'unist-util-visit'
// Matches any <img> tags with an href that starts with `/assets/` or '/public/'
const matcher = (node) =>
node.type === 'element' &&
node.tagName === 'img' &&
node.properties &&
node.properties.src &&
(node.properties.src.startsWith('/assets/') || node.properties.src.startsWith('/public/'))
// Content authors write images like `![Alt](/assets/images/foo.png`, but
// for caching purposes we want to rewrite those so they can be cached
// indefinitely.
export default function rewriteImgSources() {
return (tree) => {
visit(tree, matcher, (node) => {
const newSrc = getNewSrc(node)
if (newSrc) {
node.properties.src = newSrc
}
})
}
}
function getNewSrc(node) {
const { src } = node.properties
if (!src.startsWith('/')) return
try {
const filePath = src.slice(1)
const stats = fs.statSync(filePath)
// The size is not perfect but it's good enough. The size is
// very fast to pick up without needing to do a deep hashing of the
// image's content. It's perfectly possible that someone edits an
// image and it's size doesn't change. Although very unlikely.
// The slightest change to the image is more likely to either increase
// or decrease the image size by at least 1 byte.
// Also, because of this limitation, we're not confident to cache the
// image more than say 24h. But in the unlikely event that someone does
// edit an image and the size doesn't change, there's always the
// escape hatch that you can soft-purge all manual CDN surrogate keys.
if (!stats.size) return
const hash = `${stats.size}`
const split = src.split('/')
split.splice(2, 0, `cb-${hash}`)
return split.join('/')
} catch (err) {
console.warn(`Error trying to get a hash for ${src}`, err)
}
}