One weird trick to reduce Eleventy Image Build Times by 60%
This web site does a fair bit of build-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-duplicate multiple requests to optimize the same input 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 path from "node:path";
+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,
});
+ eleventyConfig.on("eleventy.after", () => {
+ fs.cpSync(".cache/@11ty/img/", path.join(eleventyConfig.directories.output, "/img/built/"), {
+ recursive: true
+ });
+ });
};
You could improve the above example by restricting the copy step using the process.env.ELEVENTY_RUN_MODE
environment variable.
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.
7 Comments
Zach Leatherman
(now with fixed OG image, thank you @cassidoo.co ????)
Zach Leatherman :11ty:
@stvnhrlnd the results were SHOCKING!
Zach Leatherman :11ty:
@nhoizey the transform method does use attributes, yeah. If you’re wanting programmatic access to each image transformation, the transform method is likely not for you. (use the shortcode method instead?) I’d subscribe to something like https://github.com/11ty/eleventy-img/issues… Truncated
Zach Leatherman :11ty:
@mxbck @11ty *awesome*
Seb Duggan
Ah, I thought it cached to .cache automatically, and couldn’t work out why Cloudflare Pages never used the cache on the next build… Thanks for the tip - I’ll give it a go!
Zach Leatherman
we should do that but don’t currently! we’ll probably tackle that soon!
Zach Leatherman :11ty:
@aaadaaam oh no!! ????