HTML Template vs defining HTML inside web component

2.1k views Asked by At

I can't seem to grasp or find out why you should use HTML templates with web components when you can simply define the HTML inside the web component (shadowRoot.innerHTML).

What is the benefit of creating a template and cloning it inside the web component? I can see there being a reason if two web components share the same HTML but beside that I have no idea.

Is there something fundamentally important that I'm missing?

2

There are 2 answers

0
Per Ghosh On BEST ANSWER

What is the benefit of creating a template and cloning it inside the web component?

Speed. Parsing a string and generate internal html objects takes some extra time compared to just cloning nodes. If the web component is used in many places and each will parse string and convert it to html objects. Compare that with just parsing once.

tutorial about web components

6
Danny '365CSI' Engelman On

Yes, too many blogs do document.createElement("template") where an .innerHTML will do the same ... and with less code ... and faster.

Note, Templates are not tied to the Custom Elements API or shadowDOM.
Each of the 3 Web Components technologies can be used without the other.

Templates

Templates are great when you want to store re-usable content in the HTML Document, because it does not get parsed.

In the old days we would use a <div hidden> and pray its contents did not affect the rest of the page.

Just like the old days you can read the Template.innerHTML and do whatever you want with the String value.

More modern approach is to clone the Template, just be aware that .content property is required, and you get a Document-Fragment value in return.

<template id="MY-TEMPLATE">
 <article>
  ...
 </article>
</template>

document.getElementById("MY-TEMPLATE").content.cloneNode(true)

Templates & shadowDOM

When you have Custom Elements with shadowDOM, Templates are great to define that shadowDOM content.

Why so many developers want to do HTML-in-JS and CSS-in-JS I don't understand.
If you have an HTML document, store the content there, way easier to edit.

<template id="MY-ELEMENT">
  <style>
    /* style shadowDOM here */
  </style>
  <slot></slot>
</template>

All your MY-ELEMENT then needs to do is:

super()  // or this when done in the connectedCallback
  .attachShadow({mode: 'open'})
  .append(document.getElementById(this.nodeName).content.cloneNode(true))

Performance

an innerHTML String with HTML content will get parsed for every usage.

A template is parsed once, so does save on CPU cycles, when you use the same template many many multiple times

Usage

My personal preference is to keep as much HTML (and CSS) inside <TEMPLATEs> in HTML as possible. Only when I want my components not to be configurable I use static HTML in JS, with .innerHTML, not .createElement("template") for code brevity over (minor) performance gain

Only in SDWCs (Self Destructing Web Components) that need to load/execute ASAP I contain everything inside the Component:

customElements.define('my-head',class extends HTMLElement{
  connectedCallback(){
    // generate <HEAD> content, <SCRIPTS> and <STYLE> CSS-in-JS here

    this.remove();

  }
});