From d8d1dbfcec9bd961b91b770c99eee127fb4b50ab Mon Sep 17 00:00:00 2001 From: Ricardo Date: Tue, 3 Mar 2026 12:06:46 +0100 Subject: [PATCH] fix: prevent watcher OOM by tuning eleventy-img plugin - transformOnRequest: process images on-demand in watch mode instead of all at once during rebuild (same pattern as zachleat.com) - cacheOptions: cache remote image fetches to disk (1d build, 30d watch) - concurrency: 4 (down from default ~10 based on CPU count) to limit Sharp's native memory usage from parallel image decodes Root cause: Sharp processes remote images outside V8 heap, so --max-old-space-size doesn't cap total memory. Large remote images (e.g. 3072px-wide) at concurrency 10 spike native memory enough to exceed the 3GB cgroup limit. Confab-Link: http://localhost:8080/sessions/0ec83454-d346-4329-8aaf-6b12139bf596 --- eleventy.config.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/eleventy.config.js b/eleventy.config.js index 059c624..be13e0d 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -229,11 +229,21 @@ export default function (eleventyConfig) { }); // Image optimization - transforms tags automatically + // transformOnRequest: in watch/serve mode, process images on-demand instead of all + // at once during rebuild — prevents Sharp from saturating memory with parallel decodes. + // cacheOptions: cache remote image fetches to disk so restarts don't re-download everything. + // concurrency: limit parallel Sharp operations (default scales to CPU count, ~10 on this + // server). Each large remote image can consume 20-50MB of native memory outside V8 heap. eleventyConfig.addPlugin(eleventyImageTransformPlugin, { extensions: "html", formats: ["webp", "jpeg"], widths: ["auto"], failOnError: false, + transformOnRequest: process.env.ELEVENTY_RUN_MODE !== "build", + cacheOptions: { + duration: process.env.ELEVENTY_RUN_MODE === "build" ? "1d" : "30d", + }, + concurrency: 4, defaultAttributes: { loading: "lazy", decoding: "async",