diff --git a/packages/dom/src/clone-dom.js b/packages/dom/src/clone-dom.js index 89e752986..6530616af 100644 --- a/packages/dom/src/clone-dom.js +++ b/packages/dom/src/clone-dom.js @@ -162,6 +162,13 @@ export function getOuterHTML(docElement, { shadowRootElements, forceShadowAsLigh if (forceShadowAsLightDOM) { return docElement.outerHTML; } + // With no shadow roots to embed, the getHTML()+textContent=''+outerHTML + // .replace() reassembly below just reproduces `docElement.outerHTML` while + // allocating a full-size intermediate string + replace copy. Skip it to cut + // this step's transient footprint (GC pressure) on heavy pages. + if (!shadowRootElements || shadowRootElements.length === 0) { + return docElement.outerHTML; + } /* istanbul ignore else if: Only triggered in chrome <= 128 and tests runs on latest */ if (docElement.getHTML) { // All major browsers in latest versions supports getHTML API to get serialized DOM diff --git a/packages/dom/src/serialize-dom.js b/packages/dom/src/serialize-dom.js index 1d025b505..bd8d13f5b 100644 --- a/packages/dom/src/serialize-dom.js +++ b/packages/dom/src/serialize-dom.js @@ -24,13 +24,19 @@ function doctype(dom) { return ``; } +// Un-mangle both serialization markers in one pass instead of two: +// -> +// ` data-percy-serialized-attribute-y=` -> ` y=` +// Serialized HTML can reach tens of MB and each .replace() copies the whole +// string, so folding two passes into one halves the large-string churn (GC +// pressure) per snapshot. Groups: g1 = `<`/` + tagPrefix !== undefined ? tagPrefix : `${attrSpace}${attrName}=`); // include the doctype with the html string return doctype(ctx.dom) + html; }