Zach’s ugly mug (his face) Zach Leatherman

One weird trick to reduce Eleventy Image Build Times by 60%

August 01, 2025

This web site does a fair bit of built-time Image Optimization using the HTML Transform method provided by the Eleventy Image plugin. I took a bit of a set-it-and-forget-it approach with the plugin on this site, mostly for my own convenience. My usage looked something like this:

import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";

export default function(eleventyConfig) {
	eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
		failOnError: false,
		formats: ["svg", "avif", "jpeg"],
		svgShortCircuit: true,
	});
};

Eleventy Image includes a fair number of caches and performance optimizations to make this default behavior pretty fast.

  • It uses a memory cache to de-duplicates multiple requests to optimize the same image.
  • It uses an on-request image processing engine to avoid processing images during local development.
  • It uses a hash for output file name and checks the target file location to avoid reprocessing images.

The biggest drawback with the third method is that when you’re building on a deployment server, these environments start with an empty output folder (and thus, an empty disk cache). What can we do to re-use the disk cache and avoid reprocessing unchanged images on each new deploy?

With just a few lines of configuration code to create an intermediate output folder in a location that is persisted between builds (.cache), I was able to drop my site’s build time from an embarrasing 9:40 down to a respectable 3:56 (for throughput info, the output folder has 7,779 files weighing 492.7 MB).

I think this approach is very reusable and we’ll likely bundle it into a future version of Eleventy Image. Until then, you can use it yourself by adding the following lines of configuration:

+import fs from "node:fs";
 import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";

 export default function(eleventyConfig) {
 	eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
+		urlPath: "/img/built/",
+		outputDir: ".cache/@11ty/img/",
 		failOnError: false,
 		formats: ["svg", "avif", "jpeg"],
 		svgShortCircuit: true,
 	});

+	if(process.env.ELEVENTY_RUN_MODE === "build") {
+		eleventyConfig.on("eleventy.after", () => {
+			fs.cpSync(".cache/@11ty/img/", path.join(eleventyConfig.directories.output, "img/built/"), {
+				recursive: true
+			});
+		});
+	}
 };

You may also need to persist .cache on your web host. This behavior is provided for-free if you’re using Vercel or Cloudflare Pages.

Subscribe to github.com/11ty/eleventy-img/issues/285 for future updates.


Older >
Never write your own Date Parsing Library

Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at Font Awesome and the creator/maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 85 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of CloudCannon, Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)