How To Use eleventy-img (To Optmize Images In Eleventy) With Caching (To Keep Build Times Low) On Cloudflare Pages (Which Can't Cache Optimize Images Out Of The Box)
The Problem
Cloudflare offers build caching for static site generators like Eleventy. Both are powering this blog. Great. But: It only caches the .cache
folder (in Eleventy's case) not its output folder (default is _site
, which I will heretofore use). This means that if you use the great eleventy-img plugin to optimize images when your site is build, then this plugin will add inordinate amounts of time to the build process because every build on Cloudflare means a complete redo of the whole site, including the images (which would normally be read from _site
, but this directory is empty/nonexistent on every new build on Cloudflare pages).
My site always built in just over a minute without eleventy-img activated, but with the plugin active, build times skyrocketed to 14 minutes and more. Not what you would call fast at all.
The Solution
It seems other people have had similar issues, so I was lucky to find a solution through a fellow OMG.lol user (thanks Melanie). You just have to add the following to your eleventy.config.js
:
// Image optimization: https://www.11ty.dev/docs/plugins/image/#eleventy-transform
let imageOptions = {
// Output formats for each image.
formats: ["webp", "auto"],
// widths: ["auto"], // <- this would keep the original size, which is way too big
widths: [1400, 640, 320],
failOnError: false,
htmlOptions: {
imgAttributes: {
// e.g. <img loading decoding> assigned on the HTML tag will override these values.
loading: "lazy",
decoding: "async",
}
},
sharpOptions: {
animated: true,
},
};
if(process.env.ELEVENTY_RUN_MODE === "build") {
imageOptions.outputDir = ".cache/@11ty/img/";
imageOptions.urlPath = "/img/built/";
// Copy the optimized images to the public folder after build
eleventyConfig.on("eleventy.after", () => {
cpSync(".cache/@11ty/img/", "_site/img/built/", { recursive: true });
});
}
eleventyConfig.addPlugin(eleventyImageTransformPlugin, imageOptions);
The important part is inside if(process.env.ELEVENTY_RUN_MODE === "build") {...}
.
This sets the output dir for image transformations inside of .cache
- which is preserved between builds and after eleventy is done (listening to an event) we use cpSync to copy those files to their actual place.
This takes care of the problem with the cache and still provides us with optimized images. My build times are now around two minutes - so it still has doubled the time needed - but are way more acceptable, if you ask me.
You as the visitor should notice somewhat snappier loading times for images - as the original image (often many MBs in size) - is not used as is and downscaled anymore.
P.S.: If you're wondering about the options for the plugin: I decided against including the original images in the build as these super big images are not ever displayed at full size. The width (on desktop) of the blog is 640px (and about 320px on mobile) - with images only slightly smaller, so I let eleventy create a version of the image of those sizes. I decided to forego avif
as an image format as this took too long to build on Cloudflare. I also added a 1400px version in the hopes that Echofeed would pick that up and use it on Mastodon/Bluesky. Apart from the original format (png
or jpeg
in most cases) I also now offer a webp
version, which is a lighter weight image format supported by most modern browsers.
P.P.S.: Some links. I found the workaround through this blogpost. And I also opened in the process of understanding this problem a Github issue in the plugin's repo. I am hoping that caching inside the .cache folder will become a standard cashing strategy in the future and we won't need using a workaround anymore.
-
← Previous
DailyDogo 1333 🐶 -
Next →
A Digital Garden Inspired By The Index Card