SSR with Web Components

Rendering Shadow DOM and Templates in Puppeteer

Dorian Smiley
JavaScript in Plain English

--

Rendering web components server-side using Google Puppeteer is a real challenge. Serialization of the Shadow DOM is in an experimental phase. Declarative Shadow DOM allows serialization of the Shadow DOM and can be enabled with a few easy steps. Without following these steps, you’ll be left with empty custom elements after rendering in Puppeteer.

Enable Shadow Root

For your Shadow DOM to be serialized with experimental features, you first need to set the shadowroot property of the template.

<template shadowroot="open">

Enable Experimental Web Platform Features

To serialize Shadow DOM in Puppeteer, we are going to use a proposed new function for elements: getInnerHTML. This function takes an object that exposed the includeShadowRoots property.

const html = await page.$eval('html', (element) => {
return element.getInnerHTML({includeShadowRoots: true});
});

This function is undefined without enabled experimental features. To enable this feature in your browser, go to: chrome://flags/#enable-experimental-web-platform-features. To enable this feature in Puppeteer, you must alter your launch configuration:

const args = puppeteer.defaultArgs();
// IMPORTANT: you can't render shadow DOM without this flag
// getInnerHTML will be undefined without it
args.push('--enable-experimental-web-platform-features');
const browser = await puppeteer.launch({
args
});

Define a Waits For Method

For your component execution results to be included in the output, you need to wait for rendering to finish. To do this, we query the DOM to detect the presence of a shadow root.

await page.waitForFunction(selector => !!document.querySelector(selector)?.shadowRoot, {
polling: 'mutation',
}, selector);

For more information on waitForFunction click here.

Complete Example

A complete functional example is below. If you are stuck trying to get your web components to render, copy the example and test it out. Happy Coding!

--

--

I’m an early to mid stage start up warrior with a passion for scaling great ideas. The great loves of my life are my wife, my daughter, and surfing!