From 49d80830257856e39c65450bf0492539256970d9 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Sat, 4 Apr 2026 10:12:25 +0200 Subject: [PATCH] fix: clear eleventy-img in-memory cache between builds to prevent OOM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MemoryCache singleton in @11ty/eleventy-img holds Sharp's processed image ArrayBuffers indefinitely — no clear() method, no TTL, no reset. In watch mode, external memory grows ~30-50MB per incremental rebuild (visible as rising external/buffers in process.memoryUsage()). After 20-30 rebuilds: 500MB+ of leaked native memory, pushing RSS past the 3.5GB cgroup limit. Fix: reset imgMemCache.cache = {} in eleventy.before hook. The disk cache handles persistence — the memory cache is just an in-build deduplication layer. --- eleventy.config.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/eleventy.config.js b/eleventy.config.js index 40b2f6c..5f85368 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -380,6 +380,19 @@ export default function (eleventyConfig) { // page.url is unreliable during parallel rendering, but outputPath IS correct // since files are written to the correct location. Derives the OG slug from // outputPath and replaces placeholders emitted by base.njk. + // Clear eleventy-img in-memory cache between builds to prevent native memory leak. + // The MemoryCache singleton holds Sharp ArrayBuffers (~200KB-1MB each) that never get + // freed in watch mode. After 20-30 incremental rebuilds, external memory grows from + // ~170MB to 500MB+, eventually causing OOM. Disk cache handles persistence. + const { memCache: imgMemCache } = esmRequire("@11ty/eleventy-img/src/caches.js"); + eleventyConfig.on("eleventy.before", () => { + const size = imgMemCache.size(); + if (size > 0) { + imgMemCache.cache = {}; + console.log(`[eleventy-img] Cleared in-memory cache (${size} entries)`); + } + }); + // Cache: directory listing built once per build instead of 3,426 existsSync calls let _ogFileSet = null; eleventyConfig.on("eleventy.before", () => { _ogFileSet = null; });