Blog Post

Shadow DOMs: Encapsulation in Progressive Web Applications

Published
November 3, 2017
#
 mins read
By 

in this blog post

Most modern websites include widgets from different sources for enhanced user engagement. These widgets often include social media buttons so the user can ‘like’ or share content, a video-playing widget that will automatically play content on the sidebar, etc. As the structure of the webpage becomes more complex, it’s necessary for the developers to ensure that the third-party code doesn’t collide with the base page code and create conflicts. Otherwise, the JavaScript of the base page could end up unintentionally modifying the parts of the widget and vice versa.

How do we ensure that encapsulation is achieved? Shadow DOMs to the rescue! Just as Batman is the mysterious ‘shadow’ of Bruce Wayne in protecting Gotham city, shadow DOMs provide a way to isolate portions of the main DOM, thereby achieving protection from styling, access, and modification via common means.

What is shadow DOM?

Shadow DOMs are used while building web widgets to hide the implementation details of the widget from the JavaScript and CSS that are included on the webpage. The encapsulation is achieved by overlaying the normal DOM subtree with a special document fragment that contains another subtree of nodes.

The building blocks of shadow DOM are:

Shadow Host: The element that is responsible for creating a scoped Shadow DOM subtree.

Shadow Root: The root of the DOM subtree containing the shadow DOM nodes. It is a special node, which creates the boundary between the normal DOM nodes and the Shadow DOM nodes. This boundary is what is responsible for encapsulation.

Here is an Illustration of shadow DOM:

The nodes in green represent the main DOM tree, which also contains the shadow host. This shadow host contains references to several other shadow DOM trees. At the root of each shadow DOM subtree is a shadow root. The shadow root is a special document fragment DOM node type which encapsulates its child nodes from the outside world.

However, when the webpage is rendered, the main DOM, as well as the shadow DOM, would be rendered as a single tree. While parsing, whenever the browser encounters the shadow host, the browser disregards the subsequent children nodes of the main DOM and instead the focus is shifted to the node’s shadow DOM subtree.

Implementation Details:

Creation of shadow host and root nodes can be done through JavaScript.

Example: If this is the HTML element for which the host should be created –

<div>Hi there! </div>

We just add the following JavaScript code to create the shadow DOM:

Now, the <div> tag becomes the hosting element of the shadow root whose content is “Yo!” And the original textual content (“Hi there!”) is “hidden,” as the DOM subtree under the shadow root is encapsulated.

This is how the page is rendered:

Shadow DOMs vs. iFrames

Now that we have a basic understanding of what shadow DOMs are, it is necessary for us to know why they are preferred over the traditional iFrames.

iFrames are used to assure separate scope and styling. It is designed to embed a full document within HTML documents. This means accessing values in a DOM element that is within an iFrame, from the parent document, is quite troublesome.

In contrast, shadow DOMs will provide easier encapsulation by creating another clone of the DOM or part of it.

How can we monitor the performance of pages containing iFrames or shadow DOMs?

While it is definitely possible to monitor individual pages containing such elements through Catchpoint’s web test feature, ensuring that users can complete every action (for example: click/type) is also very important and this can be done through Catchpoint’s ability to create multi-step transaction tests.

Transaction scripts in Catchpoint use Selenium commands for execution. Logic can be inserted into these scripts to perform actions like click/type, validate a text pattern, and so on.

Accessing the elements within an iFrame from the same domain can be done via Web APIs along with JavaScript.

Similarly, accessing shadow DOM elements could be done through JavaScript using the top-down approach to interact with the page.

Also, to monitor the performance of specific elements, for example, the load time of a specific button on the page (even if it is included within an iframe/shadow DOM), Catchpoint allows you to create custom metrics using the Insights feature. This feature provides greater visibility into end-to-end application performance, correlate external monitoring data to internal performance indicators, and faster identification of performance problems.

Most modern websites include widgets from different sources for enhanced user engagement. These widgets often include social media buttons so the user can ‘like’ or share content, a video-playing widget that will automatically play content on the sidebar, etc. As the structure of the webpage becomes more complex, it’s necessary for the developers to ensure that the third-party code doesn’t collide with the base page code and create conflicts. Otherwise, the JavaScript of the base page could end up unintentionally modifying the parts of the widget and vice versa.

How do we ensure that encapsulation is achieved? Shadow DOMs to the rescue! Just as Batman is the mysterious ‘shadow’ of Bruce Wayne in protecting Gotham city, shadow DOMs provide a way to isolate portions of the main DOM, thereby achieving protection from styling, access, and modification via common means.

What is shadow DOM?

Shadow DOMs are used while building web widgets to hide the implementation details of the widget from the JavaScript and CSS that are included on the webpage. The encapsulation is achieved by overlaying the normal DOM subtree with a special document fragment that contains another subtree of nodes.

The building blocks of shadow DOM are:

Shadow Host: The element that is responsible for creating a scoped Shadow DOM subtree.

Shadow Root: The root of the DOM subtree containing the shadow DOM nodes. It is a special node, which creates the boundary between the normal DOM nodes and the Shadow DOM nodes. This boundary is what is responsible for encapsulation.

Here is an Illustration of shadow DOM:

The nodes in green represent the main DOM tree, which also contains the shadow host. This shadow host contains references to several other shadow DOM trees. At the root of each shadow DOM subtree is a shadow root. The shadow root is a special document fragment DOM node type which encapsulates its child nodes from the outside world.

However, when the webpage is rendered, the main DOM, as well as the shadow DOM, would be rendered as a single tree. While parsing, whenever the browser encounters the shadow host, the browser disregards the subsequent children nodes of the main DOM and instead the focus is shifted to the node’s shadow DOM subtree.

Implementation Details:

Creation of shadow host and root nodes can be done through JavaScript.

Example: If this is the HTML element for which the host should be created –

<div>Hi there! </div>

We just add the following JavaScript code to create the shadow DOM:

Now, the <div> tag becomes the hosting element of the shadow root whose content is “Yo!” And the original textual content (“Hi there!”) is “hidden,” as the DOM subtree under the shadow root is encapsulated.

This is how the page is rendered:

Shadow DOMs vs. iFrames

Now that we have a basic understanding of what shadow DOMs are, it is necessary for us to know why they are preferred over the traditional iFrames.

iFrames are used to assure separate scope and styling. It is designed to embed a full document within HTML documents. This means accessing values in a DOM element that is within an iFrame, from the parent document, is quite troublesome.

In contrast, shadow DOMs will provide easier encapsulation by creating another clone of the DOM or part of it.

How can we monitor the performance of pages containing iFrames or shadow DOMs?

While it is definitely possible to monitor individual pages containing such elements through Catchpoint’s web test feature, ensuring that users can complete every action (for example: click/type) is also very important and this can be done through Catchpoint’s ability to create multi-step transaction tests.

Transaction scripts in Catchpoint use Selenium commands for execution. Logic can be inserted into these scripts to perform actions like click/type, validate a text pattern, and so on.

Accessing the elements within an iFrame from the same domain can be done via Web APIs along with JavaScript.

Similarly, accessing shadow DOM elements could be done through JavaScript using the top-down approach to interact with the page.

Also, to monitor the performance of specific elements, for example, the load time of a specific button on the page (even if it is included within an iframe/shadow DOM), Catchpoint allows you to create custom metrics using the Insights feature. This feature provides greater visibility into end-to-end application performance, correlate external monitoring data to internal performance indicators, and faster identification of performance problems.

This is some text inside of a div block.

You might also like

Blog post

Preparing for the unexpected: Lessons from the AJIO and Jio Outage

Blog post

Demystifying API Monitoring and Testing with IPM

Blog post

Use the Catchpoint Terraform Provider in your CI/CD workflows