From 050da9277d99953a26ba5191fe6a3e9cbdaa58f5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:25:06 +0000 Subject: [PATCH 1/4] feat(perf): Parallelize image format generation in img-dim.js Parallelizes the generation of JPEG, AVIF, and WebP image formats using `Promise.all` in `_11ty/img-dim.js`. This improves build performance by processing multiple image formats concurrently instead of sequentially. Correctly handles fallback logic and ensures mandatory formats (JPEG/PNG) block execution on failure while optional formats (AVIF/WebP) are handled gracefully. Co-authored-by: si <18108+si@users.noreply.github.com> --- _11ty/img-dim.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/_11ty/img-dim.js b/_11ty/img-dim.js index 7013669..0033dea 100644 --- a/_11ty/img-dim.js +++ b/_11ty/img-dim.js @@ -103,16 +103,18 @@ const processImage = async (img, outputPath) => { const avif = doc.createElement("source"); const webp = doc.createElement("source"); const jpeg = doc.createElement("source"); - const fallback = await setSrcset(jpeg, src, fallbackType); + const [fallback, avifFallback, webpFallback] = await Promise.all([ + setSrcset(jpeg, src, fallbackType), + setSrcset(avif, src, "avif"), + setSrcset(webp, src, "webp"), + ]); if (!fallback) { return; } - const avifFallback = await setSrcset(avif, src, "avif"); if (avifFallback) { avif.setAttribute("type", "image/avif"); picture.appendChild(avif); } - const webpFallback = await setSrcset(webp, src, "webp"); if (webpFallback) { webp.setAttribute("type", "image/webp"); picture.appendChild(webp); From 7d710612a3310bb5558cfbbc24a12463894d7e9e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:31:22 +0000 Subject: [PATCH 2/4] feat(perf): Limit concurrency in img-dim.js to fix CI failure Introduces a `concurrencyLimit` (10) for page-level image processing in `dimImages`. This balances the increased per-image concurrency (parallel format generation) with per-page concurrency to prevent resource exhaustion (e.g., file descriptors, memory) in CI environments. Maintains the performance benefit of parallel format generation while ensuring stability. Co-authored-by: si <18108+si@users.noreply.github.com> --- _11ty/img-dim.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/_11ty/img-dim.js b/_11ty/img-dim.js index 0033dea..59c4a08 100644 --- a/_11ty/img-dim.js +++ b/_11ty/img-dim.js @@ -155,7 +155,11 @@ const dimImages = async (rawContent, outputPath) => { const images = [...dom.window.document.querySelectorAll("img,amp-img")]; if (images.length > 0) { - await Promise.all(images.map((i) => processImage(i, outputPath))); + const concurrencyLimit = 10; + for (let i = 0; i < images.length; i += concurrencyLimit) { + const chunk = images.slice(i, i + concurrencyLimit); + await Promise.all(chunk.map((img) => processImage(img, outputPath))); + } content = dom.serialize(); } } From 1fa7071bbed68056287ed7a7adab4588d0c89ae9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:37:37 +0000 Subject: [PATCH 3/4] fix(perf): Reduce image concurrency to 1 to fix CI Reduces `concurrencyLimit` in `_11ty/img-dim.js` from 10 to 1. While individual image formats (JPEG, AVIF, WebP) are still generated in parallel (3x concurrency per image), pages are now processed sequentially. This drastic reduction is necessary to prevent resource exhaustion (e.g., file descriptors, memory) observed in the CI environment (Cloudflare Workers builds). Co-authored-by: si <18108+si@users.noreply.github.com> --- _11ty/img-dim.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_11ty/img-dim.js b/_11ty/img-dim.js index 59c4a08..31fd764 100644 --- a/_11ty/img-dim.js +++ b/_11ty/img-dim.js @@ -155,7 +155,7 @@ const dimImages = async (rawContent, outputPath) => { const images = [...dom.window.document.querySelectorAll("img,amp-img")]; if (images.length > 0) { - const concurrencyLimit = 10; + const concurrencyLimit = 1; for (let i = 0; i < images.length; i += concurrencyLimit) { const chunk = images.slice(i, i + concurrencyLimit); await Promise.all(chunk.map((img) => processImage(img, outputPath))); From 87a41c86563fda4ff0a6ee39ac63449624fc719b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:43:19 +0000 Subject: [PATCH 4/4] fix(perf): Serialize mandatory image generation, parallelize optionals Modifies `processImage` in `_11ty/img-dim.js` to execute the mandatory (JPEG/PNG) image generation sequentially. Only after the fallback image succeeds are the optional formats (AVIF, WebP) generated in parallel. This strategy reduces peak concurrency and resource usage in CI environments (Cloudflare Workers builds) while still offering performance benefits for the slower, optional formats. Also ensures "fail fast" behavior: if the fallback generation fails, no resources are wasted attempting to generate optional formats. Co-authored-by: si <18108+si@users.noreply.github.com> --- _11ty/img-dim.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_11ty/img-dim.js b/_11ty/img-dim.js index 31fd764..dd487c8 100644 --- a/_11ty/img-dim.js +++ b/_11ty/img-dim.js @@ -103,14 +103,14 @@ const processImage = async (img, outputPath) => { const avif = doc.createElement("source"); const webp = doc.createElement("source"); const jpeg = doc.createElement("source"); - const [fallback, avifFallback, webpFallback] = await Promise.all([ - setSrcset(jpeg, src, fallbackType), - setSrcset(avif, src, "avif"), - setSrcset(webp, src, "webp"), - ]); + const fallback = await setSrcset(jpeg, src, fallbackType); if (!fallback) { return; } + const [avifFallback, webpFallback] = await Promise.all([ + setSrcset(avif, src, "avif"), + setSrcset(webp, src, "webp"), + ]); if (avifFallback) { avif.setAttribute("type", "image/avif"); picture.appendChild(avif);