-
Notifications
You must be signed in to change notification settings - Fork 387
Description
Related to many template, template instantiation, and DOM parts discussions (but especially #777, #682, and #704) I wonder if we should add a JavaScript-based templating API?
I think JS-based templating would be extremely useful and help with a lot of issues and questions:
- Ergonomics and convenience: Templating in JS is an incredibly common thing to do on the web, yet there's no built-in API for it. Developers have often asked for a built-in declarative way to build and update DOM.
- Safety: We can provide a safe way of interpolating untrusted values into the DOM protecting against XSS.
- Clarify the MVP for DOM parts: Templating in JS can cover a lot of open questions for template instantiation, like those brought up in [templates] How featureful should the default processor be? #682, like what the expression syntax is, how to do conditionals and looping, how scoping works, etc.
- Performance: As shown by several JS libraries, the DOM Parts model can be used to construct very fast DOM renderers. Fast, stable DOM updates as a platform feature would be a performance feature.
- Improve the initial value delivered by DOM Parts: The DOM Parts model can be used for fast templating, but given some Chrome prototypes a native implementation might not be a large performance win over similar userland implementations. There is still a lot of value in offering built-in templating, however. As @rniwa said about template instantation it "provides a mechanism to easily create a template instance without having to import a third party library"
- Code size: It would also reduce code size for those that use the native feature, and possible higher-level libraries that build on top of it. The tagged template literal syntax can be a compile target for other popular template syntaxes like JSX, Mustache, and HTML-like template like Vue, Angular, Svelte, etc.
- Interoperability: If multiple user-facing template systems use this API, they could interop, ie render a JSX template into a tagged-template literal, a Mustache template into JSX, etc.
Idea
Add an HTMLElement.html template tag and an HTMLElement.render() method that would allow describing the desired DOM structure in JS, along with bound data for interpolation and updating.
Templates would be written as tagged template literals using the HTMLElement.html tag:
const {html} = HTMLElement;
const renderPost = (title, summary) = html`
<h1>${title}</h1>
<p>${summary}</p>
`;Templates would be rendered to an element with the HTMLElement.render() method:
document.body.render(renderPost('Hello World', 'This is a template'));DOM rendered from a template can be updated by re-rendering with the same template, preserving the static DOM and only updating the bindings that changed. This would be done with DOM Parts.
// Only updates the <h1> element created from the template. No other DOM updates.
document.body.render(renderPost('Hello Templates', 'This is a template'));Features
Detailed features can be worked out later, but we know there are some basics that need to be covered to make a useful DOM templating system:
- Various binding types: child, attribute, property, event listener, element.
- Auto-escaping of binding values
- Fast updates with minimal DOM mutations: re-rendering a template should only update bindings that change.
- Composition: the ability to render a child template or array of child templates into a child binding
- Extensibility: Many use cases require some customization of how a binding is processed
- Hydration: There needs to be a way to update DOM that has been pre-rendered with SSR, SSG, etc.
Prior art
The general shape of this API has been popularized by several userland libraries including hyperHTML, lit-html, and FAST.