Image optimization with headless Umbraco setup

Hi fellow Umbraco devs,

Our client is requesting us to optimize the way images are rendered on the page. It’s mostly the size of the image and the requested viewport where improvements can be made. We see that we’re retrieving the full sized image even if it’s shown in a block of 64px squared.

I took a look at the documentation and everywhere it mentions that you can use crops to optimize the image retrieval, but sadly we haven’t been able to make it work in our headless Umbraco 16 setup.

The only thing with the crops that we see is backend / c# functionality to get the crop url based on the “crop alias”. There seems to be no support for retrieving a crop url directly from the content/media delivery api.

What is needed to retrieve the correct image for the correct instance? We’ve created a cropAlias for 64px width and 64px height for instance to take as an example.

Thanks for the help!

I’m not working too much on our headless frontend (React), but I think the frontend renders an image source set, so that the browser will pick the correctly sized image.

Using the querystring parameters you can add to any media will make sure it gets parsed by ImageSharp and generate an actual image in the correct dimensions while also taking the focus point into consideration.

So, lets say someone picks an image on a node with an image picker that needs to be displayed on a page:

  • The frontend calls the content delivery api and gets the URL of the image. So this is without any sizing or crops, lets say: /media/image_example.jpg.
  • They will render an image source set that holds references to various sizes of the images.
  • They do this by using the image sharp processing commands and attach those a querystring parameters to the image:

Using the processing commands makes Umbraco render the image in the size(s) specified. You can even render in different formats (we only use webp) an it will take the focus point into consideration. The browser selects the most appropriate image from the image source set to display based on the client.

We’re using JPG images for now (I know this should be improved, but let’s say the client is not ready to make that change).

So let’s say this is the url for an image is: https://localhost:12345/media/qerdsf/image.jpg.

By adding ?width=300 it should serve me the image with width 300?

Do you happen to know if it works this way on Umbraco Cloud as well? Or is there something that is different between my local environment and the development environment on Umbraco Cloud?

When I try any of those Processing commands in my local environment, I don’t see any effect. I’ll check it with a .webp image as well

That’s exactly what it should do. You can even say ?format=webp&width=100 to generate a webp version of the image, even though the url says .jpg.

If this doesn’t work, usually something is not registered correctly, or there could be something wrong with the image cache. Or some middleware that’s messing around.

What should be registered? Should I add something in the Program.cs maybe? I’m not aware that we mess with something in the middleware, but I’m not entirely sure. I will dive into this.

We do notice that on one of our other clients, that runs Umbraco 13, it works out-of-the-box. On two other clients that run Umbraco 15 and Umbraco 16, it doesn’t work out-of-the-box.

I just played around with some settings in our Program.cs and I noticed the problem.

We had the following code in our Program.cs:

app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx =>
        {
            // Cache-Control header: 365 days (31536000 seconds)
            ctx.Context.Response.Headers.CacheControl = "public,max-age=31536000";
        }
    }
));

Removing this code seems to work. Now I can create smaller images using “?width=300” for instance.

Thanks for your help once again @LuukPeters

Also, this is pointed out here: Solved: app.UseStaticFiles( ... ) - where/when to call? Umbraco #help-with-umbraco

You should be very careful to add this middleware.

This is especially important for people who might stumble upon this page one day and want to find an explanation.