Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.

This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
This comment has been deleted
Hi, Very helpful article - Thank you! Can you add all the steps to achieve the same redirect (.jpg to .webp) with Nginx? As you know it is not that easy to convert an .htaccess file to nginx syntax. regards Nikolay Kabaivanov
To make the Vary header work on LiteSpeed too, do this:
<IfModule mod_headers.c>
# Apache appends "REDIRECT_" in front of the environment variables, but LiteSpeed does not.
# These next line is for Apache, in order to set environment variables without "REDIRECT_"
SetEnvIf REDIRECT_accept 1 accept=1
# Make CDN caching possible.
# The effect is that the CDN will cache both the webp image and the jpeg/png image and return the proper
# image to the proper clients (for this to work, make sure to set up CDN to forward the "Accept" header)
Header append Vary Accept env=accept
</IfModule>
Also check out this solution: https://github.com/rosell-dk/webp-convert/blob/master/docs/webp-on-demand/webp-on-demand.md
Hi,
Nice and helpful article, thank you!
What will happen if we don’t convert previous images and we just want to use it for new images, so if a previous jpg image doesn’t have the any related webp image, will this code will still server the jpg image?
Thank you!
This does not work for my use case, Apache2 2.4.41 running on Ubuntu 18.04.4 (64-bit) with PHP 7.4.4, when aliased directories are used. I really do not know if it did. First time trying it, and it does not work.
Yes, I emptied my cache first. Yes, I restarted the server first. Still always getting the PNG or JPEG JFIF file, instead of the WebP files. Yes, both browsers understand image/webp. I can load a WebP file directly. Yes, I did check the files served, (size and nature), and they are the big JPEG JFIF or PNG files, and not the smaller WebP files. I even had a different image with the same filename, ( testimg.jpg and testimg.webp, but of different actual images), so that I can tell them apart. (Both images are fuchsia text on a dark blue/green gradient. In one, the text says, “This is a JPEG JFIF image testimg.jpg”, (with the text box on a blue background), while the other says, “This is a WebP image testimg.webp”, (with the text box on a transparent bg).
Indeed,
<picture>
<source media="(min-width: 650px)" type="image/webp" srcset="image/K3PX5071.webp"/>
<source media="(min-width: 465px)" type="image/webp" srcset="image/K-3.TheStache-1721.webp"/>
<source media="(min-width: 650px)" srcset="image/K3PX5071.jpg"/>
<source media="(min-width: 465px)" srcset="image/K-3.TheStache-1723.jpg"/>
<source media="(min-width: 1px)" srcset="image/K3P10635.webp"/>
<img src="image/K3P10635.jpg" alt="Flowers"/>
</picture>
works with both browsers, to serve the WebP files specified. If the two first lines are removed, I get the JPEG files.
After intense reading, the issue has become clear. This solution only works with images within the document root, and sub-directories. On my server, I have several sites, and many of my images are served from a common image directory, in an aliased location.
[BEGIN unnecessary detail for clarity’s sake ]
So my server root, ($SR), is at [ /var/www ], with my main document root, ($DR), [ {http}://Phenobuntu/ ], at [ /var/www/html ], and I have other sites at [ $SR/wp ], [ $SR/drpl ], [ $SR/Projects/GanttProject ]. To top it off, the last three sites are Aliased as, [ {http}://wpbuntu/ ], [ {http}://drplbuntu/ ], and [ {http}://gnttbuntu/ ] respectively. In addition to this, I have my common CSS, PHP scripts, and images, in different directories, as, [ $SR/src/css ], [ $SR/src/theme ], and [ $SR/src/image ], respectively, (so as to maintain a consistent look across sites). These are aliased as, [ /css ], [ /theme ], and, [ / image], respectively, for each site.
Therefore, [ {http}://Phenobuntu/image/testimg.jpg ], will reference precisely the same image as, [ {http}://wpbuntu/image/testimg.jpg ], [ {http}://drplbuntu/image/testimg.jpg ], and [ {http}://gnttbuntu/image/testimg.jpg ] but, [ {http}://phenobuntu/index.html ], [ {http}://wpbuntu/index.html ], [ {http}://drplbuntu/index.html ], and [ {http}://gnttbuntu/index.html ], are all different files.
This solution, (as with all other solutions I have tried), all assume that all images are being served from the same directory —or sub-directory— as ${DOCUMENT_ROOT}. In my case, this is not so. It will work for files in the [ wpbuntu/wp-content/uploads/ ] directories and subs, or at, [ phenobuntu/iso/image/ ] but not for images at [ wpbuntu/image/ ] nor, [ phenobuntu/image/ ] directories and subs, et al.
[/END unnecessary detail for clarity’s sake ]
So I needed to come up with a solution which works globally, for aliased directories. That is why the solution was not working for me. The solution was incomplete for all use cases.
This was the solution I figured out for Apache2 version ≥2.4.35, where aliases are being used. The code has intensive internal documentation.
# BEGIN WebP replacement
# Backward compatibility ruleset for
# rewriting image.jpeg, image.jpg, or image.png to image.webp
# when and only when image.webp exists.
# This particular script IS case-sensitive, and will not work
# for image.JPEG, image.JPG, image.PNG, or iMaGe.JpEg.
# It will work, however, to replace, iMaGe.jpeg, with iMaGe.webp.
# In other words, the filename MUST be a case-sensitive match, AND
# the file suffix MUST be lower-case.
# (This assumes that your server is case- sensitive. Some servers
# may be set to case-insensitive mode. In that case, the rule will
# still work.
Options Indexes FollowSymLinks
Require all granted
# We can possibly assume that mod_rewrite is installed and enabled.
# This can be a dangerous assumption, and ought to be tested
# with <ifModule mod_rewrite.c> conditional clause.
# I was testing, and certain options do not work within in <if> statement.
# I live on the edge! (I know my server).
# Please un-comment this line. If it does not work, AND you are certain
# that mod_rewrite is installed, comment it.
<IfModule mod_rewrite.c>
# Turn on rewrite engine.
RewriteEngine on
# Ensure this matches your document root. (Usually optional).
RewriteBase /
# Do we care if the JPEG JFIF or PNG file exists? (I do not)!
# Many CMS themes only allow a JPEG or PNG file in certain places.
# This ensures that if you cannot tell the theme to use a WebP file,
# use a JPEG file in the theme, and the WebP file will be served.
# Besides, if the original file did not exist, a 404 error would
# have been returned. May as well get an image instead.
# If we care that the JPEG/PNG exists,
# (althoug it is not needed since we have a WebP replacement),
# then uncomment the next line.
# RewriteCond %{CONTEXT_DOCUMENT_ROOT}/$1.$2 -f
# We re-direct only if the browser accepts WebP images.
RewriteCond %{HTTP_ACCEPT} image/webp
# We re-direct only if the WebP equivalent exists.
# If one has neglected to upload the replacement file,
# no substitution will be made.
RewriteCond %{CONTEXT_DOCUMENT_ROOT}/$1.webp -f
# The first rule replaces the [ image.jpe?g|png ] with [ image.webp ]
# in the browser interface, and requires another server request.
# The second rule will leave the original request in the browser,
# but still serve the WebP file.
# Un-comment only one rewrite rule!
RewriteRule ^(.*)\.(jpe?g|png)$ %{CONTEXT_PREFIX}/$1.webp [R,L,T=image/webp]
# RewriteRule ^(.*)\.(jpe?g|png)$ %{CONTEXT_PREFIX}/$1.webp [L,T=image/webp]
# End the <ifModule…> statement, if it was invoked.
# Comment this line if the conditional was not used.
</IfModule>
# %{CONTEXT_PREFIX} and %{CONTEXT_DOCUMENT_ROOT} are new Apache2
# version ≥ 2.4.35 variables, which may not exists, or be the same thing,
# on older/other HTTP servers. These variables somewhat take into consideration
# the use of Aliases, and other types of server-config/site-config
# directory re-directs.
# END WebP replacement
This .htaccess file has to go in all document root directories involved. That is, in my case, I need to put it in [ $SR/html ], [ $SR/wp ], [ $SR/drpl ], [$SR/joomla ], [ $SR/Projects/GanntProject ], and [ SR$/src/image ].
For existing redirects in existing .htaccess files, place the snippet at the top of the file, to occur before other redirects. E.g., for Wordpress, place this snippet above the line marked, “# BEGIN WordPress” in the .htaccess file.
The .htaccess code contains a logical error.
The Vary header is only set when the Client sends HTTP_ACCEPT image/webp.
But the Vary header should also be sent if the client does not accept image/webp because if not, the caching system will store png/jpg in the cache and overwrite the webp version even for the clients that have webp enabled…
You can observe the error when you have caching enabled on your server and follow these steps:
Step 1. Call website: Webp images are served
Step 2. Deactivate webp in Firefox (about:config, image.http.accept to “/”) and reload wesite: Webp images are not served (as expected)
Step 3. Reactivate webp in Firefox (about:config, image.http.accept to “image/webp,/”) and reload website: webp images are still not served
The Vary header should be sent for all images, not only when the client accepts webp:
<IfModule mod_headers.c>
<FilesMatch "\.(jpe?g|png|gif)$">
Header append Vary Accept
</FilesMatch>
</IfModule>
Hello,
Is it possible to follow this procedure on the nginx webserver? is there a tutorial about it?
thank you very much
This comment has been deleted