21 August, 2022

Sitecore - Dianoga with Azure CDN (Microsoft) Classic - Limitation and Solution

Dianoga is an automatic image optimizer for the Sitecore media library. This optimizer can optimize the images and cache in Sitecore Media Cache (MediaCacheAsync) or optimize the image on the fly and return the optimized image (GetMediaStreamSync). Most of the Sitecore prod environments are enabled by CDN and the second option will fit in this scenario. If CDN is not used, then Sitecore Media Cache (MediaCacheAsync) is the right choice. 

Update - 12/16/2022: Dianoga module (6.1.0) has been updated ( to support custom header as described in the below article. 

Next-gen formats:

Next-gen images use formats with superior compression and quality characteristics compared to their GIF, JPEG, and PNG ancestors. These image formats support advanced features designed to take up less data while maintaining a high quality level, making them perfect for web use. (reference article)

An image format for the Web 

WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web faster. (reference article)

Image Optimization in an environment with Azure CDN (MS):

In order to enable the next-gen formats and let CDN cache the optimized images for subsequent requests, we need to enable a configuration in Dianoga - Dianoga.NextGenFormats.CDN.config

  • When the first media request is being made, browser will send the accepted MIME types in ACCEPT header. (The Accept header lists the MIME types of media resources that the agent is willing to process. This is a comma-separated list of MIME types, each combined with a quality factor, a parameter that indicates the relative degree of preference between the different MIME types.)

  • Dianoga uses this header value and if the browser accepts the next-gen formats, then it will process it in WebP or other formats and return the optimized images. This will be cached in CDN and it will be served for other users if another request is made. 

  • If we are using Azure CDN Classic (Microsoft), then the accept header is NOT passed to the origin server. This is a limitation in Azure CDN side. In case if you are using Azure Premium Verizon CDN, then this header will be passed to origin server and Dianoga will be able to process it without any problems.

    As of now, there is no news on whether this header will be accepted by Azure CDN. 

Possible solutions:
  1. Upgrade to Azure Premium Verizon CDN:

    We can setup Azure Premium Verizon CDN. Accept header is passed to Origin server and Dianoga will be able to optimize the image in webP format. Moreover the CDN admin portal can handle various complex caching scenarios. Customization can be applied using headers and other parameters. 

    Cost: It is costly compared to Azure CDN Classic. 2x to 3x costlier. 

  2. Pass the accept header value in a different header using Rule Engine:

    With the basic rule engine in Azure CDN, we can read the accept header sent from the browser and pass it in a different header to origin server. In the origin server, we can then read the custom header and then optimize the images. There is no need of additional cost to setup Premium Verizon CDN here. 

    Rule engine for WebP:

  • In this rule, accept header is checked whether it contains "webp" and then "image/webp" is added to a custom header named "CustomAccept". In order to execute this rule only for media files, request path rule has been added to ~/jssmedia (jss site) and ~/media requests. 

  • In Dianoga, we can check for this custom header and if the next gen format mime type is accepted by the browser using CustomAccept header, we can run the optimizer and send the optimized images. 

Some clients do no approve for Premium Verizon CDN due to cost or other factors. Tweaking the header value and pass it in a different header may be helpful. 

No comments:

Post a Comment

blockquote { margin: 0; } blockquote p { padding: 15px; background: #eee; border-radius: 5px; } blockquote p::before { content: '\201C'; } blockquote p::after { content: '\201D'; }