Skip to content

Commit dcbc2c1

Browse files
heiskrCopilot
andauthored
Cache statSync results in rewrite-asset-urls to reduce disk IO (#60390)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent cff05ea commit dcbc2c1

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

src/content-render/unified/rewrite-asset-urls.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import fs from 'fs'
22
import type { Element, Node } from 'hast'
33
import { visit } from 'unist-util-visit'
44

5+
// Process-level cache for stat results — file sizes don't change between deploys.
6+
const statCache = new Map<string, number | null>()
7+
58
// Matches any <img> tags with an href that starts with `/assets/` or '/public/'
69
function isAssetOrPublicImg(node: Node): node is Element {
710
return (
@@ -35,25 +38,27 @@ function getNewSrc(node: Element): string | undefined {
3538
const src = node.properties?.src as string
3639
if (!src.startsWith('/')) return
3740

41+
const filePath = src.slice(1)
42+
43+
// Check cache first — avoids repeated statSync for the same image
44+
if (statCache.has(filePath)) {
45+
const cachedSize = statCache.get(filePath)
46+
if (!cachedSize) return
47+
const split = src.split('/')
48+
split.splice(2, 0, `cb-${cachedSize}`)
49+
return split.join('/')
50+
}
51+
3852
try {
39-
const filePath = src.slice(1)
4053
const stats = fs.statSync(filePath)
41-
// The size is not perfect but it's good enough. The size is
42-
// very fast to pick up without needing to do a deep hashing of the
43-
// image's content. It's perfectly possible that someone edits an
44-
// image and it's size doesn't change. Although very unlikely.
45-
// The slightest change to the image is more likely to either increase
46-
// or decrease the image size by at least 1 byte.
47-
// Also, because of this limitation, we're not confident to cache the
48-
// image more than say 24h. But in the unlikely event that someone does
49-
// edit an image and the size doesn't change, there's always the
50-
// escape hatch that you can soft-purge all manual CDN surrogate keys.
54+
statCache.set(filePath, stats.size || null)
5155
if (!stats.size) return
5256
const hash = `${stats.size}`
5357
const split = src.split('/')
5458
split.splice(2, 0, `cb-${hash}`)
5559
return split.join('/')
5660
} catch {
61+
statCache.set(filePath, null)
5762
console.warn(
5863
`Failed to get a hash for ${src} ` +
5964
'(This is mostly harmless and can happen with outdated translations).',

0 commit comments

Comments
 (0)