SSR with Web Components
Rendering Shadow DOM and Templates in Puppeteer
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!