Nginx
Conditionally Serve AVIF
Why serving next generation images with Nginx?
- There's no need to change client-side code, and
-
Unlike
<picture>
tags, video posters have no standard way of specifying many URLs to fetch the optimal supported format.
Here's how
The images are uploaded with the extension appended:
- foo.jpg
- foo.jpg.avif
- foo.jpg.webp
For dispatching the most efficient format, Nginx
checks the Accept
request header. For example, Chrome 85 and up say they support AVIF by sending its MIME
type:
Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8
nginx.conf 1
http { # ... map $http_accept $img_ext { ~avif '.avif'; ~webp '.webp'; default ''; } server { # ... location /images { add_header Vary Accept; try_files $uri$img_ext $uri =404; } } }
On requests under /images
, Nginx checks the
Accept
header
($http_accept
)
to define
the custom variable $img_ext
with the extension
associated to the first matched regex of the
map
.
Then,
try_files
checks if there's
a file with that extension appended, e.g., foo.jpg.avif
, and serves it. The middle
$uri
is a fail-safe, for instance, maybe the AVIF isn't uploaded yet.
Lastly, Vary: Accept
is set as a response header. This is only needed
if the server has caching reverse proxies in front (e.g., intercepting CDNs).
Otherwise, those proxies would always serve the same format sent to the first client that
requested the particular image.2