Feature: Serve WebP and AVIF behind Cloudflare via configurable image format option#22
Feature: Serve WebP and AVIF behind Cloudflare via configurable image format option#22roboes wants to merge 3 commits into
Conversation
|
The issue is that Cloudflare does not respect the Vary header. Therefore it does not make sense to use the Accept header to determine the image format when using Cloudflare. The first response will get cached, and future requests will be responded to with the same image. See: https://developers.cloudflare.com/cache/advanced-configuration/vary-for-images/ Instead, when using Cloudflare, we should disregard the Accept header entirely. In this case we could decide to always allow WebP compression, as by now it is almost universally supported. Using AVIF would be more aggressive, as it would exclude some users. (Again, browser format detection will not work due to Cloudflare caching not respecting Vary.) In other words, if Cloudflare is detected, the Accept header should not be read. |
|
Thanks for the clarification - the PR has been updated to reflect this. The Accept header is no longer read for Cloudflare requests, and For non-Cloudflare requests, the existing Accept header negotiation is preserved unchanged. The Please let me know if this satisfies the concern or if further changes are needed. |
|
The server check doesn't make sense. A remote API is used to compress images since most servers don't have the necessary tools or old versions, and image compression causes a lot of load. So that should be removed. The preferred type image/avif needs to get forwarded to the service: https://github.com/kiboit/phast/blob/master/src/Filters/Image/ImageAPIClient/Filter.php#L98-L100 I need to add AVIF support in the service as well before we can merge this. |
|
Thanks for the clarification - all 3 points make sense. Changes made:
Please let me know if anything else needs adjusting. |
Description
Phast currently disables modern image format serving entirely when a Cloudflare proxy is detected:
This is a safe default - Cloudflare can cache a response and serve it to browsers that didn't send the original
Acceptheader - but it means sites running behind Cloudflare with Polish disabled get no benefit from Phast's image format conversion, even though their server is fully capable of it.WebP sits at roughly 97% global browser support in 2026, and AVIF has crossed 95% globally, with full support in Chrome, Firefox, Edge, and Safari 16.4+. Leaving these formats unused behind Cloudflare is a significant missed optimisation opportunity.
Solution
This PR introduces a
cloudflare-image-formatconfig key underimageswith three options:off(default)webpavifThe setting is
offby default, so existing behaviour is fully preserved unless the user explicitly opts in.Changes
src/Environment/DefaultConfiguration.phpAdds the new config key to the
imagesarray:src/Filters/Image/Image.phpAdds the missing
TYPE_AVIFconstant alongside the existingTYPE_WEBPandTYPE_JPEG:src/Services/Images/Service.phpgetParams()- replaces the hard Cloudflare gate with config-aware logic. AVIF is attempted first (better compression), WebP is the fallback.makeResponse()- excludes AVIF fromVary: Accept, consistent with the existing PNG exclusion.serverSupportsAvif()- runtime check across three contexts:wp_image_editor_supports(), which internally validates both GD and Imagick and abstracts PHP version differences.Imagick::queryFormats()for AVIF (requireslibheif).imageavif()was introduced in PHP 8.1; PHP 7.x and 8.0 returnfalsecleanly via thePHP_VERSION_IDguard).browserSupportsAvif()/browserSupportsWebp()- updated to usestr_contains(), replacing the previousstrpos() !== falsepattern.When should users enable this?
Only when Cloudflare Polish is disabled. If Polish is active, Cloudflare already handles format negotiation at the CDN edge - enabling this setting would result in double conversion with no benefit.
If Polish is disabled and Phast is handling image optimisation directly, enabling
webporavifallows Phast to serve modern formats to the ~97% and ~95% of browsers that support them respectively, without relying on the CDN.Compatibility
imageavif()presentlibheifcompiled inwp_image_editor_supports()