5 ms·
The key observation about HTML templates is that usually large portions of them don't change with new data. There is static content, and even with lots of dynam
by spankalee 4y ago
The key observation about HTML templates is that usually large portions of them don't change with new data. There is static content, and even with lots of dynamic bindings they're tied together in a static structure.
So the vdom approach of processing all the static parts of a template during a diff is just extremely wasteful, especially for fairly common cases like conditionally rendering a node before some static content.
Ideally you already know what changed, and can just update the parts of the template that depend on it. In JS that typically requires a compiler, complexity, and custom semantics (like Solid). But you can get very, very close to that ideal with plain JS syntax and semantics by capturing the static strings and the dynamic values separately then only comparing the dynamic values on updates.
This is what we do with lit-html and why I think tagged template literals are nearly perfect for HTML templates.
With tagged template literals, an expression like:
html`<h1>Hello ${name}!</h1>`
is passed to the `html` tag function as an array of strings `['<h1>Hello ', '!</h1>']` and an array of values: `[name]`, and the strings array is the same every time you evaluate the expression, so you can compare it against the previous template and only update the values in the DOM if it's the same.
It's a really efficient way to render and update DOM with a pretty simple conceptual model that requires no compiler at all - it's all runtime. I think it's straightforward and powerful enough to be standardized at some point too.
- svachalek 4y agoI'm sure there's a different concept in there somewhere, but what you described sounds exactly like vdom.
- thomasikzelf 4y agoLet's call it vdata. Data diffing instead of DOM diffing.
- spankalee 4y agoThis model doesn't represent DOM nodes, it represents entire templates. And there's no per-node diff - you only compare bound values. So the structure of templates is entirely static.
- fassssst 4y agoI mean in the native Windows app world you just have your “ViewModel” raise an event with the name of the property that changed, and the UI layer just goes and assigns the new value to the appropriate element(s). Much simpler and easier to debug than vdom approaches.
- dmix 4y ago> The key observation about HTML templates is that usually large portions of them don't change with new data. Isn't this a core idea underneath the https://fresh.deno.dev/ https://fresh.deno.dev/ "islands" and I believe the https://astro.build/ https://astro.build/ framework when they confronted issues around hydration/SSR? https://www.patterns.dev/posts/islands-architecture/ https://www.patterns.dev/posts/islands-architecture/ Clearly there's some overhead via the vDOM and simply using React-like templates when building large blocks of HTML. But if the bulk can be rendered server-side that overhead isn't an issue. So you can address this by simply reducing the data binding to the bare minimum of HTML that actually need to be interactive. That way you can use the same templating and component systems app-wide but the default is still static-first. That said - the Cons section notes: "The architecture is not suitable for highly interactive pages like social media apps which would probably require thousands of islands." But at that scale there's often far more performance concerns than vDOM vs compiler vs [some better optimized templating system], where the benefits aren't as straightforward (as linked below https://twitter.com/dan_abramov/status/1135423065570127872 https://twitter.com/dan_abramov/status/1135423065570127872).
- spankalee 4y agovdom is overhead server-side too. When rendering HTML on the server you really want to stream longer pre-allocated strings as much as possible. The serialization overhead of converting many small objects to individual HTML tags shows up in profiles. And when you want low latency and the ability to handle high loads, it matters.
- synalx 4y agoThis is also a core design principle of Angular - the compiler extracts the static template structure and generates code to update dynamic bindings within it.
- spankalee 4y agoYes, but it turns out that you don't actually need a compiler for that. You can do it in a runtime that's very small because the standard JS syntax already separates the static structure for you.
- deleted 4y ago[deleted]
- mmis1000 4y ago> So the vdom approach of processing all the static parts of a template during a diff is just extremely wasteful, especially for fairly common cases like conditionally rendering a node before some static content. Vue 3 already just render the whole static contents to string in this case. And this is one of the selling point of vue 3. It just happily serialize a big chunk of static template into string and create fragment on runtime with it. So client don't need to create static elements one by one. Besides that, it also mark that static content as "just don't diff it, it won't change", so runtime won't even try to diff it. https://shorturl.at/aijOQ https://shorturl.at/aijOQ Switch to the js panel and you will realize that it already serialize the whole v-node thing into html on build time.
- mock-possum 4y agoGood to see Lit called out here, I love the lit-html approach to using tagged template literals to define views.