11ty 3.0 and the Image Plugin

Mar 28, 2024

Note: This was originally intended to be solely about the image plugin. While I was setting that up, I discovered that I needed to upgrade 11ty to the 3.0 beta. Keep reading to learn why! * 11ty supports images by default, and I have it working - but it doesn't do any optimization (that I'm aware of). The Chrome lighthouse analysis points out that images are being served far too large, and aren't responsive.

The official eleventy-img plugin is meant help with this by doing some magical optimizations.

Installation and Setup

Following the instructions was simple enough, until I got to the part about using Eleventy Transform to automatically process all images in my output folder. Turns out, this requires 11ty 3.0, which is still in testing. I'm going to have to upgrade if I want to use this method of processing, which I do. Let's see how this goes!

Updating to 11ty 3.0

Running npm install @11ty/eleventy@canary --save-exact and crossing my fingers.

Wow. It just worked, perfectly. No issues whatsoever. Nice!

Back to the images plugin

Ok, now I'm adding the specified boilerplate to the .eleventy.js config file. That looks like this, added to my module.exports:

  eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
    // which file extensions to process
    extensions: "html",

    // Add any other Image utility options here:

    // optional, output image formats
    // formats: ["webp", "jpeg"],
    formats: ["avif", "webp", "png"],

    // optional, output image widths
    widths: [200, 400, 800, 1000,"auto"],

    // optional, attributes assigned on <img> override these values.
    defaultAttributes: {
      loading: "lazy",
      decoding: "async",
      sizes: "(max-width: 640px) 90vw, 90vw",
    },
  });

And it just works. It dropped the size of an image in a previous post from 29.6kb down to 7.6kb, a ~74% reduction. That is significant, especially if I had multiple images in a post.

Sizes

It successfully changed the format, saving a lot of bandwidth, but it didn't change the size of the image in pixels. Turns out, that was due to my CSS. I had to set this:

.main img {
    width:100%;
    height: auto; /* Or object-fit: cover; */
  }

It's not perfect, but it's far improved from before!