W3C

– DRAFT –
Template Instantiation

26 March 2025

Attendees

Present
dandclark, masonf, Monhamed_Mansour, rniwa, smaug, xiaoqian
Regrets
-
Chair
Ryosuke Niwa
Scribe
masonf

Meeting minutes

rniwa: this is about DOM Parts. We worked with Google on this. Point to specific location in the DOM to update it easily.

rniwa: people use comment nodes as markers to do this, and use regular mutation stuff to mutate them. Need to maintain the comments, etc.

rniwa: performance benefit maybe. Based on Mason's experiment, no.

masonf: it depends. Some benchmarks it wins, some it loses, by 10-20%.

rniwa: are there other benefits? Might still be worth adding. Or best leave to userland.

rniwa: issue filed in DOM (link?) about document fragments whose nodes do not get removed when inserted

rniwa: like a wrapper documentfragment that stays in the tree

rniwa: similar to DOM parts, they're isomorphic. Different semantics, but same concepts and use cases.

rniwa: it came up that maintaining start/end comment nodes can be tricky. Those could be removed. DOM Parts - stays in the DOM tree.

rniwa: still ergonomic benefit.

masonf: we need to figure out how much to do. Losing some things (like maintaining references) was slower.

rniwa: different use cases need different featuresets

rniwa: though that makes it more complicated.

rniwa: Olli was concerned about complexity already.

rniwa: maybe there's a simple proposal that we can implement

smaug: the other documentfragment proposal might be simpler?

rniwa: proposal has a polyfill, so it is concrete to some extent

smaug: some open issues

masonf: a new node that looks like display:content

rniwa: also doesn't get seen by querySelector

rniwa: and doesn't affect rendering

rniwa: insert and remove nodes - same capacity

smaug: that might complicate things - new node type isn't really there but is there. But shadow dom - does it slot? Etc.

rniwa: we did consider this when we thought of DOM Parts. We came to the conclusion that the complexity is harder than it seems.

rniwa: once you try to nail down all the details, it might be more complicated than DOM Parts. Might be can of worms.

rniwa: new node type - selectors only work with elements, not Nodes, so maybe that's easy. Direct selectors parent>child might be tough.

rniwa - what about nesting these things

smaug: likely surprising performance consequences

rniwa: both approaches have downsides, particularly performance.

mmansour: for dom parts, placing variables inside. Let's say we want for loops and when conditions?

mmansour: todo app, put the template for that into the DOM - replace the variables. But let's say you want a todo list - many items.

mmansour: nested DOM Parts? Append each one?

mmansour: I'm building a web component framework - SSR in any language - isomorphic apps. Template parts works nicely. Define templates on serving time, on hydration - to add new item, take template from main document, add variables, done.

mmansour: for development, we need for loops and conditions.

masonf: JS object as state, arrays of strings, add those to DOM Parts

rniwa: this might be more template instantiation more than DOM Parts

rniwa: browser engine has native template engine - in the future. This (DOM Parts) is just a piece of that.

rniwa: template instantiation is hard, so break into pieces we can build

mmansour: because it's opinionated? Is it the syntax?

rniwa: that plus it's complicated. Need to do looping/conditionals, standardizing that plus customization is tough.

mmansour: I'll share proposal we (Edge) have with a WebUI framework. Treats HTML/JS/CSS as main foundations, rather than React.

mmansour: built in rust, looks through web components, generates entire declarative shadow DOM. Can be any language. Render entire website at once.

mmansour: tough part - we have to do JS manipulation to do for loops and conditionals.

mmansour: we believe react and angular are making the web slower, and if we use the platform, it'll be faster.

smaug: DOM Parts aren't better in terms of performance.

mmansour: I'll build a template for for loops, but that'll make it harder for the user. This is my template for todo list, a list of template parts, need to develop in a different way.

rniwa: is there still something implementable?

smaug: as of now, it doesn't look promising for anything

smaug: this would complicate things

masonf: maybe someone else can make it fast

masonf: I don't want my perf feedback to be the thing that kills this API

rniwa: maybe if the author feedback is good - if this helps the developer experience, maybe worth it.

rniwa: if this really is a building block toward template instantiation

rniwa: just like custom elements provided a way to define components, we could do the same thing for templates.

masonf: is this a building block toward template instantiation?

rniwa: we tried to make it that, yeah. But if there isn't value to DOM Parts by itself, maybe we can just skip ahead to template instantiation.

smaug: if it's template instantiation that people want, then maybe

masonf: some frameworks have components but don't use templates

rniwa: in DOM parts there seems to be a kernel of something useful. Ability to have a comment-like object that marks positions. Frameworks might like it.

rniwa: would that be beneficial to add to browsers?

rniwa: adds a bunch of complexity, but no performance gain, maybe not worth it.

rniwa: there are a ton of people on issue 736 - maybe shows interest in this concept.

rniwa: something useful. Not clear what people need exactly. Ask people on 736 - what are you looking for?

masonf: you might get lots of feedback.

taylore: question about DOM Parts - for ease of implementation - is it worth it? Just for organization purposes? Does it make the developer experience better?

taylore: maybe ship it but it won't improve performance. But we can use it as a building block. Provides another mechanism for developers to use.

rniwa: we've added things that improve ergonomics but not performance in the past. E.g. querySelector()

rniwa: need to balance the cost also

masonf: queryselector might be a good model - it got optimized over time. Maybe that'll happen for DOM Parts.

rniwa: for 736 - if we add DOM Parts or special documentfragment, will it get used in a lot of frameworks? If yes, let's pursue. If not, we shouldn't do this.

masonf: maybe don't ask generally on 736, but since we've decided DOM Parts and the special document fragment are similar complexity, just ask on 736 if they like DOM Parts as-is?

rniwa: we need more framework authors to get involved.

rniwa: maybe that's a good idea to ask on 736

smaug: ask what DOM operations are slow currently, maybe

smaug: then also ergonomics

rniwa: latest discussion on 736 was maybe formalize comment node hack. Identify comment nodes in a certain format and manipulate those.

smaug: API implementation might be simpler

masonf: the API isn't that complicated, keeping track of nodes is the hard part. So that sounds the same maybe?

rniwa: next step: go to 736 and ask about DOM Parts. Would people use it? Why not? Or why not but you would use the documentfragment thing?

rniwa: what's the difference - that's the interesting question

rniwa: it's easy to hand-wave a solution, but the devil is in the details

masonf: I agree

rniwa: I'll try to come up with a proposed question and share the question before asking

taylore: existing frameworks - if we do DOM Parts, frameworks will adopt that and abandon their existing implementations.

masonf: don't change the developer-facing side, but change the guts

rniwa: maybe more interoperable components could be built though

taylore: helpful because you might be able to build more things like mmansour - interoperable components

rniwa: I agree.

smaug: but the native parts implementation must be faster. They won't use if it isn't faster.

rniwa: for framework authors there needs to be a benefit. Just a different thing won't fly.

rniwa: we'll have to see

mmansour: is it slower because of looping through

rniwa: we have all JS knowledge, so it should be able to be faster

mmansour: queryselector the nodes and replace the content

{discussion about performance}

{discussion about lack of attendance here}

mmansour: to ask developers: if you have DOM Parts, and you're compiling templates, could you make it faster?

rniwa: if you're building on the server, you're doing a bunch of work anyway

mmansour: it'll be similar for template instantiation.

rniwa: maybe good segway

mmansour: the FAST framework (similar to Lit) - declarative templates. To support hydration for SSR web components, can't depend on JS templating. Do declarative templating, with "repeat" and "when" conditionals and loops.

mmansour: walking through template tag to see where the special conditions are. Do a build step - produce a JS representation, and maybe template parts help. Walk character by character to parse the template string.

rniwa: if you have to do that client-side, DOM Parts helps. Avoid tree walks. But if you're server-side compiling, benefits diminish.

mmansour: I'll ping the FAST people

5 minute break

<rniwa> RRSAgent: start meeting

rniwa: this is the ultimate crown jewel - create templates and make the result more usable and mutable via easy JS

rniwa: a while ago we (Apple) made a proposal

<rniwa> https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Template-Instantiation.md

rniwa: it's been a while. Would be good to come back to it soon. Template engine use case seems clear.

rniwa: want to replace content and update content. Bidirectional bindings. DOM to JS and back

rniwa: allow for loops and conditionals in template engines

rniwa: original proposal was to make a template processor. Hook for the library author to hook into template engine in the browser and customize behavior.

rniwa: callbacks for template clone, etc.

rniwa: that stuff seems still useful because the semantics need to be delegates to the template engine, because that would be overkill and too opinionated.

rniwa: questions?

mmansour: two ways to do that. 1 is do everything declaratively in the DOM. 2 is build time produce JS representation of template. 2 is react.

mmansour: which one is faster?

mmansour: assume startup performance isn't an issue. Now you need to add another item to the DOM, like a banner. Which is faster?

mmansour: is precompiled JS always faster?

rniwa: we haven't done perofrmance testing extensively.

{the answer might be here? krausest/js-framework-benchmark)

rniwa: when you make a big list, you have a lot of repetition. You need to repeat all of the <li> elements.

rniwa: potential benefit: you could say I just want 10 <li>'s and only transfer one of them.

mmansour: I've prototyped this kind of thing. Yes, if you build a web component with 1000 items. Yes, the template is repeated 1000 times. You're assuming you're using slots for things like the name, etc. You're dependant on slots.

mmansour: slots are only element based. You can't slot things like an attribute.

mmansour: broken for my use case. I want 1000 components, and need to replace the attributes for each.

rniwa: attributePart is exactly that

rniwa: drive update from JS. Because attributes are exposed as a JS property, that's do-able.

rniwa: all updates come from JS object. You can update attribute or content value.

mmansour: how without JS?

rniwa: you're relying on object attributes - what you're using to render the component.

mmansour: if you're SSRing 1000 contacts. You want each one to have a tel attribute. How do you render that?

rniwa: embed a JSON object and render from the JSON

rniwa: can be implemented in the browser, so avoid a flash

mmansour: isn't there a cost to switching to/from JS?

rniwa: want a blob of JSON, then a bunch of templates that all use that single JSON to generate the DOM tree

mmansour: that's the proposal?

rniwa: yes

rniwa: initial proposal maybe doesn't have all of that, but that's where we want to go.

rniwa: one feedback from Mozilla was that it was too complex. That's why we wanted DOM Parts first.

rniwa: because DOM Parts wasn't necessarily a performance win, maybe come back to this

rniwa: might be a win

mmansour: I do like what you said. One thing: <slot>s if you render a header slot, then a bunch of HTML and then another default slot. When you render the page. It'll render the template and slots without the children, then the children.

mmansour: if you use slots a lot, that's bad.

Slots are streamable - replace the slot and it changes. Slots - no attributes - just entire elements can be replaced.

mmansour: managing slots was good, except for no attribute support.

mmansour: but I like the JSON at the start, templates at the end approach. I don't know how lists work. One for every element item.

rniwa: lists we didn't tackle in the proposal yet. Rest was complicated enough.

rniwa: the browser can tackle the list. Then we just have a blob of data and some templates and the browser constructs the DOM tree.

rniwa: should be a performance win

mmansour: what about experimentation. Swap one button out for another button component, without reloading the page.

rniwa: dynamic reloading? For that, scoped custom element registries is best

mmansour: refresh the template in real time?

rniwa: yeah, just replace the template and the JSON populates the templates automatically

mmansour: good for developer hot refresh use cases

rniwa: much faster than diffing virtual DOM also

mmansour: ship it

rniwa: in a perfect world, great

mmansour: svg support?

rniwa: in theory yes. One template with N instances, each referring back to the original.

mmansour: SVGs get heavyweight everytually. You can use <use>, but can't do that cross-root.

mmansour: would you get a new copy of the SVG?

rniwa: yes, duplicate the tree, so not shared.

rniwa: but automatic. So if you update the top level template, the rest propagates automatically.

rniwa: maybe we go back to the drawing board that we can build directly, without going through DOM Parts first.

dandclark: I agree finding smaller pieces is a good idea, but I'm not sure which part

masonf: DOM Parts is lower level, so it doesn't have most of this stuff.

mmansour: I'd love to have this

mmansour: what can you strip out of the proposal to make it shippable?

<rniwa> https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Template-Instantiation.md

rniwa: go to section 3.1

templateInstance, and an update function

rniwa: keep calling update to update the DOM tree, from the JS object. Automatically replace mustache syntax with JS content.

mmansour: I used a dotted syntax for my framework

mmansour: this is flattened JSON structure, right? What if you have a large user object, user.name - do we support structures?

rniwa: that's the intent. Not in the proposal. But chaining support is natural.

rniwa: if you go to 3.2, there are template parts, and custom callbacks

mmansour: maybe that's something that can be chopped out. Not needed for SSR.

mmansour: for SSR we just need to hydrate and remove duplicate nodes

rniwa: section 3.3 is conditionals and loops.

mmansour: you used handlebars

rniwa: go to just before section 4 - use the directive attribute,

mmansour: I just used template called for, etc. What about explicit tags like <for each>

mmansour: lots of tooling with ASTs - if you see a non-tag character, syntax highlighting breaks, etc.

rniwa: nice to bring it to the platform, IDEs will get updated so this gets recognized.

rniwa: ergonomic benefit of bringing this to the web

mmansour: no includes any more, just use components

mmansour: in handlebars, you include template. Web components don't need that.

rniwa: we want to tackle this because we think it'll benefit the platform.

mmansour: 3.2 can be cut. 3.3 just needs more clarity on what's needed. 4 is how it works.

mmansour: template parts with conditions and instances. Dan, can you implement that?

mmansour: I wonder what happens with React - they won't use this. FAST, Lit, regular developers who don't use frameworks - they will

rniwa: if there is a performance win, others might use it also, as a compile target.

rniwa: once you have looping and conditionals, server side rendering will be much better than anything today.

mmansour: at build time in Rust, we create a native handler that renders the entire page. On the runtime side, it'll call that function. It's just a bunch of functions concatenated, with holes in the middle for data

rniwa: yep, that's what we were going for - this might change the web in a good way. Let the platform do the work.

mmansour: I trust the web platform fro rendering and interactivity, but not good at waiting for JS to load

dandclark: we've been involved, but not currently trying to drive it

rniwa: we made the proposal, but haven't put effort into it really. Doing other things.

rniwa: we're now interested in putting effort into this area.

mmansour: I can help also, I'm passionate about this stuff.

rniwa: there seems to be some goodness here that might be worth doing.

rniwa: we need to understand the benefits also.

masonf: rniwa maybe implement it?

rniwa: there's a polyfill somewhere, perhaps dig that up and update it?

rniwa: prototyping would be a good idea

rniwa: every framework invents templating, why isn't this in the browser?

mmansour: next thing people will ask is data bindings

mmansour: after that, reflection - getting API schema from web components

rniwa: once we implement, more things will come out, naturally.

{discussion of scoped custom element registries}

Minutes manually created (not a transcript), formatted by scribe.perl version 244 (Thu Feb 27 01:23:09 2025 UTC).

Diagnostics

Succeeded: s/thought/though

Succeeded: s/JA/JS

Maybe present: mmansour, taylore

All speakers: dandclark, masonf, mmansour, rniwa, smaug, taylore

Active on IRC: breakout-bot, masonf, rniwa, smaug, xiaoqian