←back to thread

69 points jdkoeck | 5 comments | | HN request time: 0s | source
Show context
MrJohz ◴[] No.44438306[source]
My biggest criticism of this design is that the author doesn't seem to have explored how Svelte, Vue Vapor or SolidJS work at all. The design seems largely based on the idea that rendering the template is a cheap operation, and that it can be done repeatedly whenever values change. So it's fine to have something like html`<div>${arr.map(el => html`...${el}...`)}</div>`, because each time the array changes, rendering every item in the list is a cheap operation. And it's typically cheap because it's rendering to a VDOM-like structure, and the more expensive diffing happens later.

But modern signal-based frameworks tend to work on the basis that doing these of rendering for each change is unnecessary, and so you should only update the relevant part of the DOM. This means rendering as seldom as often, in particular when handling conditionals and lists. This is why both SolidJS and Vue Vapor both have helpers for rendering lists and conditional elements, because if you just use `.map` and the ternary operator, things aren't going to work as you'd expect. Svelte has its own syntax but in principle works very similarly.

This proposal feels like it's very oriented around the React/Lit VDOM mechanism, with a handful of Preact-like concessions to signals where they are relatively easy to retrofit into a VDOM-like system. The problem is that these sorts of frameworks are heavyweight, slow, cumbersome things, because they're doing so much extra work. Codifying that sort of inefficiency directly into the browser seems like a terrible idea.

My second biggest criticism of this proposal is that I'm really struggling to see the benefit of it, i.e. who it's for. It can't be for framework compatibility, because it's not addressing any of the issues that actually make frameworks incompatible with each other (different state/context mechanisms, different lifecycles, etc). It can't be to codify common rendering idioms and optimise them by letting the browser implement them natively, because, as discussed, the proposal doesn't leave a lot of room for well-optimised frameworks. So I guess the idea is to ensure that the browser has a built-in web framework to make it easier for people to build complex web applications without needing to import lots of dependencies.

But if you're building a complex web application, the sort that needs specialised rendering like this, the overhead of a web framework is probably pretty minimal anyway. And if you're building simpler sites with minor interactivity, this sort of rendering system is complete overkill. You'd be better if writing a wrapper around document.createElement and going from there.

replies(2): >>44438815 #>>44438861 #
throwitaway1123 ◴[] No.44438815[source]
> This is why both SolidJS and Vue Vapor both have helpers for rendering lists and conditional elements

Haven't these tagged template libraries coalesced around the html`<${SomeComponent}><//>` syntax for custom components (including control flow components like Solid's `For` component)? The readme for Ryan Carniato's Lit DOM Expressions library includes this example for instance [1]:

  const view = html`
    <table class="table table-hover table-striped test-data">
      <tbody>
        <${For} each=${() => state.data}
          >${row => html`
            <tr>
              <td class="col-md-1" textContent=${row.id} />
              <td class="col-md-4">
                <a onClick=${[select, row.id]}>${() => row.label}</a>
              </td>
              <td class="col-md-1">
                <a onClick=${[remove, row.id]}
                  ><span class="glyphicon glyphicon-remove"
                /></a>
              </td>
              <td class="col-md-6" />
            </tr>
          `}<//
        >
      </tbody>
    </table>
  `;
The author of the article mentions this very briefly, where he writes "For JSX-style references you would need to use binding syntax like <${MyComponent}>". The Preact author's htm tagged template library uses this convention as well [2].

[1] https://github.com/ryansolid/dom-expressions/tree/7fd9f86f1b...

[2] https://github.com/developit/htm

replies(1): >>44439047 #
1. MrJohz ◴[] No.44439047[source]
The syntax exists, yes, but the intention of the proposal seems to be that users will use standard JS conditional/looping constructs, and even pushes this as one of the reasons that this style of template works so well here. But these are exactly the type of constructs that you need to avoid if you want fine-grained reactive DOM updates.
replies(1): >>44439324 #
2. throwitaway1123 ◴[] No.44439324[source]
JSX was also created with the intention of using traditional conditional/looping constructs, but that hasn't stopped Solid and Preact from repurposing it for fine grained reactivity. Preact's signal implementation has Solid-like Show/For components [1].

I won't speak for the author of the proposal, but given that Lit itself has special control flow mechanisms for conditionals and loops (the cache and repeat directives respectively [2][3]), I can't imagine the proposal being too opposed to these mechanisms.

[1] https://github.com/preactjs/signals/blob/eae850a9f3aa62e505a...

[2] https://lit.dev/docs/templates/conditionals/#caching-templat...

[3] https://lit.dev/docs/templates/lists/#the-repeat-directive

replies(1): >>44439758 #
3. MrJohz ◴[] No.44439758[source]
I'm sorry, I don't think I'm being clear enough because we keep on talking past each other here.
replies(2): >>44440055 #>>44446619 #
4. throwitaway1123 ◴[] No.44440055{3}[source]
I certainly don't think I'm talking past you, but I can't force you to elaborate.
5. throwitaway1123 ◴[] No.44446619{3}[source]
The repeat directive I mentioned as an example of a custom looping control flow construct used in a tagged template is the exact same one another commenter later mentioned (and you responded to) here by the way: https://news.ycombinator.com/item?id=44441002