Dynamic Fragments

Edgemesh® Server is designed to optimize the performance of your website effortlessly, requiring minimal code modifications. While it seamlessly handles most content caching, there may be cases where fully dynamic pages, such as carts and accounts, need to bypass caching to ensure real-time data accuracy. In such situations, Edgemesh® offers Platform Plugins specifically tailored to handle platform-specific, fully dynamic pages.

However, there are scenarios in which the majority of your page content can be safely cached, except for a small portion that requires dynamic server-side logic. Allowing this small percentage of dynamic content to prevent caching would result in a significant loss in performance.

Dynamic Content

To address this issue, Edgemesh® Server introduces a powerful feature called Dynamic Fragments. By utilizing the <dynamic> HTML element, developers can easily tag sections of HTML as dynamic, instructing Edgemesh® Server to fetch and inject the specific content from the upstream server directly to the client-side. This bypasses the edge cache, ensuring real-time and accurate data for the dynamic sections while still benefiting from the caching advantages for the rest of the page.

With Edgemesh® Server's Dynamic Fragments, you can strike the perfect balance between caching performance and dynamic functionality, enhancing your website's overall user experience. Embrace this simple yet effective solution to optimize your dynamic content without compromising on speed and efficiency.

Inline Content

Let's say you have a page with a server-side rendered variable on your / route such as:

Original Server Rendered Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<div class="welcome">Welcome {{ customer.name }}</div>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

This full HTML would not be cacheable due to the templated {{ customer.name }} variable. The cached response would contain the name of the customer that initially cached the response and subsequent cached responses would be inaccurate. Enter Edgemesh® Server Dynamic Fragments.

It is as simple as wrapping your dynamic content with the <dynamic></dynamic> tag.

Dynamic Fragment Added
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div class="welcome">Welcome {{ customer.name }}</div>
</dynamic>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

Edgemesh® Server will then detect all dynamic elements, strip the inner content for the cached response and replace the uncached inner content client-side, preserving all the request credentials. The resulting HTML will be:

Final HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div class="welcome">Welcome John Doe</div>
<dynamic>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

The <dynamic> tag is otherwise inert and should not affect the page's layout. So even if your page is not optimized by Edgemesh Server (staging stores, preview themes, bypassed pages) everything will render correctly regardless.

Dynamic Attribute

Similar to the <dynamic> element, a dynamic attribute can be applied to any element containg dynamic content:

Dynamic Attribute
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<div dynamic class="welcome">Welcome {{ customer.name }}</div>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

This is useful for when adding a <dynamic> element would cause undesired side effects. While the <dynamic> element itself is inert, it may confuse existing CSS selectors that rely on children. For example: div.title:first-child. In the previous example the first child would resolve to the <dynamic> element, which should not be the target of any css rules. Using the dynamic attribute will allow you to mark your content as dynamic without the need for refactoring your stylesheets.

Edge Expanded URLs

The <dynamic> element also accepts a single attribute src. Providing this attribute will instruct Edgemesh® Server to expand this fragment with the content found at the URL provided to the src attribute. This ensures there is only one request from the client to fetch all dynamic content for a given page. The src attribute's content will overwrite any of the inner content, so it's intended to be used with empty content. The closing tag is required.

Edge Expanded Fragments
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic src='/custom-view'><dynamic>
<dynamic src='https://my.social.feed'><dynamic>
</body>
</html>

If the URL provided to the src attribute results in an error, a console log will be injected to provide you with the information necessary to debug the edge expanded fragment.

Injected Content

In some cases, your platform or app ecosystem may inject code containing dynamic content that you don't have direct access to or control over. This can pose challenges when it comes to caching and optimizing such content. Edgemesh® Server understands this need and offers a convenient solution.

With Edgemesh® Server, you can utilize a meta tag that allows you to define CSS selectors for specific content elements that should be treated as dynamic. By specifying these selectors, Edgemesh® Server can identify and handle the dynamic content appropriately, ensuring that it is fetched from the upstream server and injected client-side, bypassing the caching mechanisms.

Consider the following HTML. You know that the app will inject dynamic content with the customer-name id and the favorite-products class.

Your HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="em-dynamic" content="#customer-name, .favorite-products">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
</body>
</html>

The app injects the dynamic content before delivering it to the client:

After Apps Inject Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="em-dynamic" content="#customer-name, .favorite-product">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<div id="customer-name">John Doe</div>
<ul>
<li class='favorite-product'>Product 1</li>
<li class='favorite-product'>Product 2</li>
<li class='favorite-product'>Product 3</li>
<ul>
</body>
</html>

Edgemesh® Server will use the provided selectors to mark the matching content as dynamic before delivering the page to the client.

Final HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="em-dynamic" content="#customer-name, .favorite-product">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div id="customer-name">John Doe</div>
</dynamic>
<ul>
<dynamic><li class='favorite-product'>Product 1</li></dynamic>
<dynamic><li class='favorite-product'>Product 2</li></dynamic>
<dynamic><li class='favorite-product'>Product 3</li></dynamic>
<ul>
</body>
</html>

Default Content

In order to prevent layout shifts while your dynamic content is loading in, dynamic fragments accept the default parameter that will use its contents as the default content while the dynamic client is fetched by the client. The default content is then replaced with the dynamic content. The attribute accepts any HTML content or the special key word preserve. The preserve keyword will retain the elements original content. This attribute works on both element and attribute based dynamic fragments.

In this example we want to disaply some default content for before the dynamic content loads in. This will prevent layout shifts and give the user something to look at while the dynamic content loads. Your source code would look like this:

Dynamic Fragment with Default Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic default="Welcome!">
<div class="welcome">Welcome {{ customer.name }}!</div>
<dynamic>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

The response from the server will have the default content:

Response from the Server
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div class="welcome">Welcome!</div>
<dynamic>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

After the dynamic content loads the full message will replace the dynamic content:

After Dynamic Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div class="welcome">Welcome John Doe!</div>
<dynamic>
<ul>
<li><a href="/product-1"><img src="/product-1.png" /></a>
<li><a href="/product-2"><img src="/product-2.png" /></a>
<li><a href="/product-3"><img src="/product-3.png" /></a>
</ul>
</body>
</html>

Setting the default attribute to preserve will keep the original content and replace it with the dynamic content:

Preserve Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic default="preserve">
<div class="cart-bubble">{{ cart.item_count }}</div>
<dynamic>
</body>
</html>

The response from the server would show the edge cached value:

Preserved Content from Server
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div class="cart-bubble">0</div>
<dynamic>
</body>
</html>

Then the dynamic content will replace the preserved content:

Preserved Content Replaced with Dynamic Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Store</title>
</head>
<body>
<div class="title">My Store</div>
<dynamic>
<div class="cart-bubble">2</div>
<dynamic>
</body>
</html>

This is useful when you want to keep the original content and can tolerate it being stale for a moment while the dynamic content is fetched. A good usecase would be the item count bubble on a cart icon.

Previewing Dynamic Content

The dynamic content for a page is fetched from the /em-cgi/dynamic/:pathname route. If you want to see the dynamic content for a page such as /pages/rewards, you can go to /em-cgi/dynamic/pages/rewards in your browser, or perform a GET request from your favorite HTTP client (postman, cURL, etc).

Debugging Dynamic Fragments

When the server responds to the document request, dynamic fragment attributes are stripped to save on transfer size. If you need to see what attributes are set on dynamic fragments, you can set the ?em-debug search parameter and the full markup will be returned from the server. This allows you to inspect how dynamic fragments are configured in developer tools without having to refer to your source code.

Example
https://mystore.com/?em-debug

Made withby Edgemesh Corporation