Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      CodeSOD: One Last ID

      September 24, 2025

      9 Ways AI Code Generation in React.js Reduces Technical Debt for Product Teams

      September 24, 2025

      GitHub details upcoming changes to improve security in wake of Shai-Hulud worm in npm ecosystem

      September 24, 2025

      Syncfusion restructures Essential Studio into multiple different suites to provide greater flexibility for developers

      September 24, 2025

      Distribution Release: Kali Linux 2025.3

      September 23, 2025

      Distribution Release: SysLinuxOS 13

      September 23, 2025

      Development Release: MX Linux 25 Beta 1

      September 22, 2025

      DistroWatch Weekly, Issue 1140

      September 21, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      A Stream-Oriented UI library for interactive web applications

      September 24, 2025
      Recent

      A Stream-Oriented UI library for interactive web applications

      September 24, 2025

      billboard.js 3.17.0: ✨ New Axis Customization, Label Styling & Image Labels!

      September 24, 2025

      AEM and Cloudflare Workers: The Ultimate Duo for Blazing Fast Pages

      September 24, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Distribution Release: Kali Linux 2025.3

      September 23, 2025
      Recent

      Distribution Release: Kali Linux 2025.3

      September 23, 2025

      Distribution Release: SysLinuxOS 13

      September 23, 2025

      How I Configure Polybar to Customize My Linux Desktop

      September 23, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»AEM and Cloudflare Workers: The Ultimate Duo for Blazing Fast Pages

    AEM and Cloudflare Workers: The Ultimate Duo for Blazing Fast Pages

    September 24, 2025

    If you’re using Adobe Experience Manager as a Cloud Service (AEMaaCS), you’ve likely wondered what to do with your existing CDN. AEMaaCS includes a fully managed CDN with caching, WAF, and DDoS protection. But it also supports a Bring Your Own CDN model.

    This flexibility allows you to layer your CDN in front of Adobe’s, boosting page speed through edge caching.

    The Challenge: Static vs. Dynamic Content

    Many AEM pages combine static and dynamic components, and delivering both types of content through multiple layers of CDN can become a complex process.

    Imagine a page filled with static components and just a few dynamic ones. For performance, the static content should be cached heavily. But dynamic components often require real-time rendering and can’t be cached. Since caching is typically controlled by page path—both in Dispatcher and the CDN—we end up disabling caching for the entire page. This workaround ensures dynamic components work as expected, but it undermines the purpose of caching and fast delivery.

    Sling Dynamic Includes Provides a Partial Solution

    AEM provides Sling Dynamic Includes (SDI) to partially cache the static content and dynamic content using placeholder tags. When a request comes in, it merges the static and dynamic content and then delivers it to the customer.

    You can learn more about Sling Dynamic Include on the Adobe Experience League site.

    However, SDI relies on the Dispatcher server for processing. This adds load and latency.

    Imagine if this process is done on the CDN. This is where Edge Side Includes (ESI) comes into play.

    Edge-Side Includes Enters the Chat

    ESI does the same thing as SDI, but it uses ESI tags on the cached pages on the CDN.

    ESI is powerful, but what if you want to do additional custom business logic apart from just fetching the content? That’s where Cloudflare Workers shines.

    What is Cloudflare Workers?  

    Cloudflare Workers is a serverless application that can be executed on the CDN Edge Network. Executing the code in edge locations closer to the user location reduces the latency and performance because the request does not have to reach the origin servers.  

    Learn more about Cloudflare Workers on the Cloudflare Doc site.

    ESI + Cloudflare Workers

    In the following example, I’ll share how Cloudflare Workers intercepts ESI tags and fetches both original and translated content.

    How to Enable ESI in AEM

    1. Enable SDI in AEM Publish: /system/console/configMgr/org.apache.sling.dynamicinclude.Configuration
    2. Add mod_include to your Dispatcher config.
    3. Set no-cache rules for SDI fragments using specific selectors.

    Note: Set include-filter.config.include-type to “ESI” to enable Edge Side Includes.

    Visit this article for more detailed steps on how to enable SDI, Dispatcher configuration.  

    Writing the Cloudflare Worker Script

    Next, write a custom script to intercept the ESI tag request and make a custom call to the origin to get the content, either from the original or translated content.

    addEventListener('fetch', (event) => { 
    
      event.respondWith(handleRequest(event.request)); 
    
    }); 
    
    async function handleRequest(request){ 
    
    //You can update the url and set it to your local aem url in case of local development 
    
    const url = new URL(request.url); 
    
    const origin = url.origin; 
    
    // You can modify the headers based on your requirements and then create a new request with the new headers 
    
    const originalHeaders = request.headers; 
    
                const newHeaders = new Headers(originalHeaders); 
    
    //Append new headers here 
    
    const aemRequest = new Request(url, { 
    
                        headers: newHeaders, 
    
                        redirect: 'manual', 
    
                    }); 
    
    // Get the response from the Origin 
    
    try{ 
    
    const aemresponse = await fetch(aemRequest); 
    
    // Get the content type 
    
    const contentType = aemresponse.headers.get("Content-Type") || ""; 
    
    // If the content type is not “text/html”, return the response as usual or as per requirement, else check if the content has any “esi:include” tag 
    
    If(!contentType.toLocaleLowerCase().includes("text/html")){ 
    
    //return  
    
    } 
    
    //fetch the HTML response 
    
                const html = await aemresponse.text(); 
    
    if(!html.includes("esi:include")){ 
    
    //content doesn’t have esi tag, return the response 
    
    } 
    
    return fetchESIContent(aemresponse, html, origin) 
    
    } 
    
    } 
    
     
    
    async function fetchESIContent(originResponse, html, origin) { 
    
        try{ 
    
       
    
          //RegEx expression to find all the esi:include tag in the page 
    
          const esiRegex = /<esi:include[^>]*ssrc="([^"]+)"[^>]*/?>/gi; 
    
       
    
          //fetch all fragments and replace those 
    
          const replaced = await replaceAsync(html, esiRegex, async (match, src) => { 
    
            try { 
    
              const absEsiUrl = resolveEsiSrc(src, origin); 
    
              const fragRes = await fetch(absEsiUrl, {headers: {"Cache-Control" : "no-store"}}); 
    
              console.log('Fragment response',fragRes.statusText) 
    
              return fragRes.ok ? await fragRes.text() : "Fragment Response didn't return anything"; 
    
            } catch (error) { 
    
              console.error("Error in fetching esi fragments: ",error.message); 
    
              return ""; 
    
            } 
    
          }) 
    
       
    
          const headers = appendResponseHeader(originResponse) 
    
          // Add this header to confirm that ESI has been injected successfully  
    
           headers.set("X-ESI-Injected", "true"); 
    
       
    
          return new Response(replaced, { 
    
            headers, 
    
            statusText: originResponse.statusText, 
    
            status: originResponse.status 
    
          }) 
    
        } 
    
        catch(err){ 
    
          new Response("Failed to fetch AEM page: "+ err.message, {status: 500}) 
    
        } 
    
      } 
    
     
    
    // Function to fetch content asynchronously 
    
    async function replaceAsync(str, regex, asycFn) { 
    
        const parts = []; 
    
        let lastIndex = 0; 
    
        for( const m of str.matchAll(regex)){ 
    
            //console.log("ESI Part of the page:: ",m) 
    
            parts.push(str.slice(lastIndex, m.index)); 
    
            parts.push(await asycFn(...m)); 
    
            lastIndex = m.index + m[0].length; 
    
        } 
    
        parts.push(str.slice(lastIndex)); 
    
        return parts.join(""); 
    
    }

    Bonus Tip: Local Testing With Miniflare

    Want to test Cloudflare Workers locally? Use Miniflare, a simulator for Worker environments.

    Check out the official Miniflare documentation.

    You Don’t Need to Sacrifice Performance or Functionality

    Implementing ESI through Cloudflare Workers is an excellent way to combine aggressive caching with dynamic content rendering—without compromising overall page performance or functionality. 

    This approach helps teams deliver faster, smarter experiences at scale. As edge computing continues to evolve, we’re excited to explore even more ways to optimize performance and personalization.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleHow Salesforce Is Transforming Digital Experience With Agentic AI 
    Next Article billboard.js 3.17.0: ✨ New Axis Customization, Label Styling & Image Labels!

    Related Posts

    Development

    A Stream-Oriented UI library for interactive web applications

    September 24, 2025
    Development

    billboard.js 3.17.0: ✨ New Axis Customization, Label Styling & Image Labels!

    September 24, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    CVE-2025-50106 – Oracle Java SE, Oracle GraalVM for JDK, Oracle GraalVM Enterprise Edition 2D Remote Takeover Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-6248 – Lenovo Browser Cross-Site Scripting Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Zuckerberg says people without AI glasses will be at a disadvantage in the future

    Web Development

    CVE-2025-38224 – Kvaser PCIEFD Linux Kernel Slab Out-of-Bounds Write

    Common Vulnerabilities and Exposures (CVEs)

    Highlights

    News & Updates

    Mark Zuckerberg says OpenAI and Anthropic researchers are flocking to Meta’s AI camp for these 2 big reasons — aside from the inaccurately reported $100 million signing bonuses

    July 15, 2025

    Meta CEO Mark Zuckerberg claims top talent from Anthropic and OpenAI are excited to join…

    How much energy does a single chatbot prompt use? This AI tool can show you

    April 24, 2025

    Rilasciata AxOS 25.06: La distribuzione GNU/Linux che ridefinisce l’esperienza utente

    June 2, 2025

    CVE-2025-47780 – Asterisk CLI Permissions Bypass Vulnerability

    May 22, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.