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
This commit is contained in:
Ricardo
2026-03-03 12:06:46 +01:00
parent 760058d0e4
commit d8d1dbfcec

View File

@@ -229,11 +229,21 @@ export default function (eleventyConfig) {
}); });
// Image optimization - transforms <img> tags automatically // Image optimization - transforms <img> 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, { eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
extensions: "html", extensions: "html",
formats: ["webp", "jpeg"], formats: ["webp", "jpeg"],
widths: ["auto"], widths: ["auto"],
failOnError: false, failOnError: false,
transformOnRequest: process.env.ELEVENTY_RUN_MODE !== "build",
cacheOptions: {
duration: process.env.ELEVENTY_RUN_MODE === "build" ? "1d" : "30d",
},
concurrency: 4,
defaultAttributes: { defaultAttributes: {
loading: "lazy", loading: "lazy",
decoding: "async", decoding: "async",