1

I am using the following, trying to serve webp images from Magento using Nginx and Varnish as caching.

Added to /etc/nginx/mime.types

 image/webp webp;

Added to main nginx.conf

http {
map $http_accept $webp_suffix {
            default   "";
            "~*webp"  ".webp";
          }
}

Added to my-site.conf for Magento 2 server block

location /media/ {
        try_files $uri $uri/ /get.php?$args;

        location ~ ^/media/theme_customization/.*\.xml {
            deny all;
        }

        location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|webp)$ {
            add_header Cache-Control "public";
            add_header X-Frame-Options "SAMEORIGIN";
            expires +1y;
            try_files $uri$webp_suffix $uri$webp_suffix/ /get.php?$args;
            
        }

But I still get jpg images instead of webp. What am I doing wrong?

1 Answers1

2

When the map is defined like:

map $http_accept $webp_suffix {
    default       "";
    "~image/webp" ".webp";
}

And when the try_files is:

try_files $uri$webp_suffix $uri$webp_suffix/ /get.php$args;

It means that when request URI is /media/image.jpg, nginx will look for image.jpg.webp if user's HTTP Accept header contains image/webp.

So, you need to append the .webp extension to all your image file names, instead of replacing the extension.

Edit:

For this to work on any caching server beyond original server, the cache needs to cache different versions of the URL.

To accomplish this, one needs to add

add_header Vary Accept;

to nginx configuration. This tells the upstream cache that it should store different of the URL based on user's Accept header.

So, in your case, Varnish should be configured to obey the Accept header.

Cloudflare is another problem. It does not support Vary: Accept header at all, so this approach of serving WebP images does not work with Cloudflare out of the box.

It can be worked around by adding a Cloudflare worker, which extracts the Accept header from the requests, and defines cache keys based on it.

Tero Kilkanen
  • 34,499
  • 3
  • 38
  • 58
  • Thanks a lot for explaning the issue! – Nikos Klavdianos Apr 03 '21 at 15:30
  • 1
    @NikosKlavdianos you will also need to amend changes to your Varnish VCL in order to vary cache based on the presence of webp in Accept: client headers. Otherwise, Varnish will just cache the first time accessed image type (depending on what the first loading client supports webp or not) – Danila Vershinin Apr 04 '21 at 12:31
  • Thanks for the clarification. I am still struggling to load the webp images. I think it's the Cloudflare I use and I'll remove that from the stack. Could you be more specific about default.vcl? – Nikos Klavdianos Apr 05 '21 at 13:29
  • I updated my answer to include more information about caching. – Tero Kilkanen Apr 05 '21 at 13:51
  • https://findwork.dev/blog/caching-tricks-with-cloudflare-workers/ is a good starting point for creating Cloudflare worker. It deals with mobile / desktop choice, but the core concept is the same. – Tero Kilkanen Apr 05 '21 at 14:57