<template id="component">
<div id="header">
<h3 id="title">{{ title }}</h3>
<h4 id="sub-title">Written by life</h4>
</div>
<div id="body">
<slot></slot>
<button id="button">click me</button>
</div>
</template>
<template id="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Amet aperiam corporis culpa deserunt dicta distinctio iste
laboriosam laudantium modi, molestiae molestias necessitatibus
neque nihil nisi omnis praesentium quam saepe totam ut velit.
Adipisci architecto atque dignissimos doloremque dolores ex
impedit in inventore nemo nulla repudiandae sequi veritatis
voluptas voluptate, voluptatibus?
</p>
</template>
<div id="wrapper" hidden></div>
const fillTitle = shadow => {
shadow.getElementById('title').textContent = 'Lorem ipsum dolor sit amet';
};
const attachEvents = shadow => {
const button = shadow.getElementById('button');
button.addEventListener('mousedown', () => {});
button.addEventListener('mouseup', () => {});
button.addEventListener('click', () => {});
button.addEventListener('dragstart', () => {});
button.addEventListener('dragend', () => {});
button.addEventListener('dragcancel', () => {});
button.addEventListener('dragmove', () => {});
button.addEventListener('custom', () => {});
};
const renderWithHTML = shadow => {
shadow.innerHTML = document.getElementById('component').innerHTML;
};
const renderWithClone = shadow => {
shadow.appendChild(document.getElementById('component').content.cloneNode(true));
};
const wrapper = document.getElementById('wrapper');
const content = document.getElementById('content').innerHTML;
const examplesHTML = `<my-component-a>${ content }</my-component-a>`.repeat(5000);
const examplesClone = `<my-component-b>${ content }</my-component-b>`.repeat(5000);
class MyComponent extends HTMLElement {
render() {};
constructor() {
super();
const shadow = this.attachShadow({
mode: 'open'
});
this.render(shadow);
fillTitle(shadow);
attachEvents(shadow);
}
}
class MyComponentA extends MyComponent {
render(shadow) {
return renderWithHTML(shadow);
};
}
class MyComponentB extends MyComponent {
render(shadow) {
return renderWithClone(shadow);
};
}
window.customElements.get('my-component-a') || customElements.define('my-component-a', MyComponentA);
window.customElements.get('my-component-b') || customElements.define('my-component-b', MyComponentB);
window.renderTestHTMLString = () => wrapper.innerHTML = examplesHTML;
window.renderTestCloneNode = () => wrapper.innerHTML = examplesClone;
renderTestHTMLString();
renderTestCloneNode();
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
HTML string | |
Clone node |
Test name | Executions per second |
---|---|
HTML string | 10.3 Ops/sec |
Clone node | 3.2 Ops/sec |
Let's break down the provided benchmark and explain what is being tested, the different approaches compared, their pros and cons, and other considerations.
Benchmark Definition
The benchmark measures the performance of rendering two types of HTML content: an HTML string and a cloned node. The tests are designed to evaluate the efficiency of rendering WebComponents with custom elements.
Options Compared
There are two main options being compared:
renderTestHTMLString()
: This test renders the same HTML string (examplesHTML
) repeatedly, using window.renderTestHTMLString()
. The purpose is to measure the performance of rendering an HTML string as a single unit.renderTestCloneNode()
: This test clones the content
node from the template, and then appends it to the wrapper element (wrapper
). The goal is to measure the performance of cloning and appending nodes.Pros and Cons
renderTestHTMLString()
Pros:
Cons:
renderTestCloneNode()
Pros:
Cons:
Other Considerations
The benchmark uses a WebComponent framework with custom elements, which adds complexity to the test. Additionally, the tests use Chrome 128 as the browser, which may not be representative of other browsers or versions.
Library Used
The benchmark uses the customElements
API to define and register custom elements. The MyComponent
, MyComponentA
, and MyComponentB
classes are used to create instances of these custom elements. The shadow
element is used to render the components in a separate context, which helps to isolate the rendering performance.
Special JS Feature/Syntax
The benchmark uses ES6+ syntax, including classes, template literals, and arrow functions. This may make it less accessible to developers familiar with older JavaScript versions or other programming languages.
In summary, the benchmark is designed to evaluate the performance of rendering WebComponents with custom elements in a controlled environment. The two tests measure different aspects of rendering performance: HTML string rendering and cloning and appending nodes. Understanding the pros and cons of each approach can help developers optimize their code for better performance.