Skip to content

Commit 9f67144

Browse files
committed
The VDOM Revolution: How We Render UIs from a Web Worker #7168 WIP
1 parent 99abf6b commit 9f67144

1 file changed

Lines changed: 77 additions & 53 deletions

File tree

learn/blog/v10-deep-dive-vdom-revolution.md

Lines changed: 77 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,79 +9,97 @@ communicate UI changes from a worker to the main thread? And what's the best lan
99
built by a machine, for a machine?
1010

1111
This article explores the solutions to those problems, focusing on two key concepts:
12-
1. **JSON Blueprints:** Why using structured data is a more powerful way to define complex UIs than traditional HTML.
12+
1. **Three Philosophies of UI Definition:** How Neo.mjs offers multiple layers of abstraction for building UIs, from high-level declarative trees to low-level VDOM blueprints.
1313
2. **Asymmetric Rendering:** How using different, specialized strategies for creating new UI vs. updating existing UI leads to a more performant and secure system.
1414

1515
*(Part 4 of 5 in the v10 blog series. Details at the bottom.)*
1616

1717
---
1818

19-
## Part 1: The Blueprint - Why JSON is the Language of the Future UI
19+
## Part 1: The Three Philosophies of UI Definition
2020

21-
The web industry has spent years optimizing the delivery of HTML. For content-heavy sites, Server-Side Rendering (SSR)
22-
and streaming HTML is a brilliant solution. But for complex, stateful applications—the kind needed for AI cockpits, IDEs,
23-
and enterprise dashboards—is sending pre-rendered HTML the ultimate endgame?
21+
Before diving into *how* the VDOM works, it's crucial to understand *what* we're building. Neo.mjs offers three distinct
22+
approaches to defining your UI, each with its own strengths.
2423

25-
We've seen this movie before. In the world of APIs, the verbose, heavyweight XML standard was supplanted by the lighter,
26-
simpler, and more machine-friendly JSON. We believe the same evolution is inevitable for defining complex UIs.
24+
### 1. The OOP Way: Abstracting the DOM Away
2725

28-
Instead of the server laboring to render and stream HTML, Neo.mjs is built on the principle of **JSON Blueprints**.
29-
The server's job is to provide a compact, structured description of the component tree—its configuration, state, and
30-
relationships. Think of it as sending the architectural plans, not pre-fabricated walls.
26+
The most powerful and abstract way to build complex applications in Neo.mjs is the Object-Oriented approach. You compose
27+
your UI by creating `Container` classes and declaratively defining their child `items` as a configuration object.
3128

32-
This approach has profound advantages, especially for the AI-driven applications of tomorrow:
29+
```javascript
30+
// Example of a declarative component tree
31+
import Container from '../../../../src/container/Base.mjs';
32+
import Toolbar from '../../../../src/toolbar/Base.mjs';
33+
import Button from '../../../../src/button/Base.mjs';
34+
35+
class MyComponent extends Container {
36+
static config = {
37+
className: 'MyComponent',
38+
layout : {ntype: 'vbox', align: 'stretch'},
39+
items : [{
40+
module: Toolbar,
41+
items : [{module: Button, text: 'Button 1'}]
42+
}, {
43+
ntype: 'component',
44+
html : 'Content Area'
45+
}]
46+
}
47+
}
48+
```
3349

34-
* **Extreme Data Efficiency:** A JSON blueprint is drastically smaller than its equivalent rendered HTML, minimizing data transfer.
35-
* **Server De-Loading:** This offloads rendering stress from the server, freeing it for core application logic and intensive AI computations.
36-
* **AI's Native Language:** This is the most critical advantage for the next generation of applications.
37-
An LLM's natural output is structured text. Asking it to generate a valid JSON object that conforms to a component's
38-
configuration is a far more reliable and constrained task than asking it to generate nuanced HTML with embedded logic
39-
and styles. The component's config becomes a clean, well-defined API for the AI to target, making UI generation less
40-
error-prone and more predictable.
41-
* **True Separation of Concerns:** The server provides the "what" (the UI blueprint); the client's worker-based engine
42-
expertly handles the "how" (rendering, interactivity, and state management).
50+
With this method, you are not thinking about HTML, divs, or even the VDOM. You are describing your application in terms
51+
of its logical components and their relationships. This is the classic approach for building robust, enterprise-scale
52+
applications where separation of concerns and maintainability are paramount.
4353

44-
This philosophy—that structured JSON is the future of UI definition—is not just a theoretical concept for us. It
45-
is the core engine behind a new tool we are developing: **Neo Studio**. It's a multi-window, browser-based IDE
46-
where we're integrating AI to generate component blueprints from natural language. The AI doesn't write JSX; it
47-
generates the clean, efficient JSON that the framework then renders into a live UI. It's the first step towards
48-
the vision of scaffolding entire applications this way.
54+
### 2. The Functional Way: Direct VDOM Control with JSON Blueprints
4955

50-
`[Screenshot of the Neo Studio UI, showcasing a generated component from a prompt]`
56+
For functional components, or when you need to dynamically generate UI structures, you can drop down a level of
57+
abstraction and work directly with **JSON Blueprints**. This is the "native language" of the Neo.mjs rendering engine.
58+
59+
The component's `render()` method returns a structured JSON object that describes the VDOM tree.
5160

52-
JSON blueprints are the language. But what about the developer experience? While JSON is the perfect target for an AI,
53-
developers are often most comfortable with an HTML-like syntax.
61+
This approach has profound advantages:
5462

55-
This is why the recent v10.3.0 release introduces the best of both worlds.
63+
* **Extreme Data Efficiency:** A JSON blueprint is drastically smaller than its equivalent rendered HTML.
64+
* **AI's Native Language:** This is the most critical advantage for the next generation of applications. An LLM's
65+
natural output is structured text. Asking it to generate a valid JSON object that conforms to a component's API is
66+
a far more reliable and constrained task than asking it to generate nuanced HTML.
67+
* **Ultimate Control:** It gives you precise, programmatic control over the generated VDOM.
5668

57-
### The Best of Both Worlds: Developer-Friendly HTML Templates
69+
This philosophy is the engine behind our AI-powered **Neo Studio**, which generates these JSON blueprints from natural
70+
language prompts.
5871

59-
While JSON is the framework's native tongue, we recognize the universal fluency of HTML. To that end, we've introduced an
60-
intuitive, HTML-like syntax for defining component VDOMs, built directly on standard JavaScript Tagged Template Literals.
72+
`[Screenshot of the Neo Studio UI, showcasing a generated component from a prompt]`
73+
74+
### 3. The Onboarding Ramp: Developer-Friendly HTML Templates
75+
76+
While JSON is the framework's native tongue, we recognize the universal fluency of HTML. To lower the barrier to entry
77+
and provide a familiar authoring experience, the recent [v10.3.0 release](../../.github/RELEASE_NOTES/v10.3.0.md)
78+
introduced an intuitive, HTML-like syntax built on standard JavaScript Tagged Template Literals.
6179

6280
```javascript
6381
// Inside a component's render() method:
6482
return html`
6583
<div class="my-container">
6684
<p>${this.myText}</p>
67-
<${Button} text="Click Me" handler="${this.onButtonClick}" />
85+
<${Button} text="Click Me" onClick="${this.onButtonClick}" />
6886
</div>
6987
`;
7088
```
7189

72-
Crucially, this is **not JSX**. It's a feature built on our core principle of a **zero-builds development experience**.
73-
Your code runs directly in the browser without a mandatory build step.
90+
This is the **beginner mode**—an easy on-ramp for developers new to the framework. Crucially, this is **not JSX**. It's
91+
built on our core principle of a **zero-builds development experience**, running directly in the browser.
7492

7593
To achieve this without sacrificing performance, we use a dual-mode architecture:
76-
1. **Development:** Templates are parsed live in the browser by the lightweight `parse5` library.
77-
2. **Production:** A build-time process transforms the templates directly into the same optimized JSON VDOM blueprints
78-
discussed above. The parser is completely removed, resulting in zero runtime overhead.
94+
1. **Development:** Templates are parsed live in the browser.
95+
2. **Production:** A build-time process transforms the templates directly into the same optimized **JSON VDOM blueprints**
96+
used by the functional approach. The parser is completely removed, resulting in zero runtime overhead.
7997

80-
This gives developers a choice: use the raw power of JSON blueprints when generating UIs with AI or other tools, or use
81-
the familiar comfort of HTML templates for hand-crafting components, all while the same powerful, asymmetric rendering
82-
engine works its magic under the hood.
98+
This gives developers a choice: start with the familiar comfort of HTML templates, or use the raw power of JSON
99+
blueprints. For complex functional components, we still recommend using JSON directly for maximum clarity and performance.
100+
But for simpler components or for developers who prefer it, the template syntax is a powerful and welcome alternative.
83101

84-
Now let's look at that engine.
102+
All three philosophies feed into the same revolutionary rendering engine. Now let's look at that engine.
85103

86104
---
87105

@@ -150,17 +168,23 @@ However, this had a limitation. The `updateDepth` was an "all or nothing" switch
150168
Consider a toolbar with ten buttons. If the toolbar's own structure needed to change *and* just one of those ten buttons
151169
also needed to update, the v9 model wasn't ideal.
152170

153-
This is the exact challenge that **v10's Asymmetric Blueprints** were designed to solve.
154-
155-
The new `VDomUpdate` manager and `TreeBuilder` utility work together to create a far more intelligent update payload.
156-
When the toolbar and one button need to change, the manager calculates the precise scope. The `TreeBuilder` then
157-
generates a partial VDOM blueprint that includes:
158-
1. The full VDOM for the toolbar itself.
159-
2. The full VDOM for the *one* button that is changing.
160-
3. Lightweight `{componentId: 'neo-ignore'}` placeholders for the other nine buttons.
161-
162-
The VDOM worker receives this highly optimized, asymmetric blueprint. When it sees a `neo-ignore` node,
163-
it completely skips diffing that entire branch of the UI.
171+
This is the exact challenge that **v10's Asymmetric Blueprints** were designed to solve. The magic lies in a
172+
sophisticated **pre-processing and negotiation phase** that happens entirely within the App Worker, *before* anything
173+
is sent to the VDOM worker.
174+
175+
Here's how it works:
176+
1. **Negotiation:** When the button needs to update, it doesn't immediately send a request. Instead, its `VdomLifecycle`
177+
mixin looks up the component tree and asks, "Is my parent (the toolbar) already planning an update?"
178+
2. **Aggregation:** If the toolbar is indeed about to update, the button merges its request into the toolbar's. The
179+
`VDomUpdate` manager acts as the central coordinator, tracking these merged requests. This single step dramatically
180+
reduces the number of expensive cross-worker messages.
181+
3. **Asymmetric Build:** The toolbar, now responsible for its own changes *and* the button's, calls the `TreeBuilder`
182+
utility. The `TreeBuilder` constructs a highly specific blueprint: it includes the full VDOM for the toolbar itself,
183+
the full VDOM for the *one* button that merged its update, and lightweight `{neoIgnore: true}` placeholders for the
184+
other nine buttons.
185+
186+
The VDOM worker receives this pre-optimized, asymmetric blueprint. When it sees a `neo-ignore` node, it completely
187+
skips diffing that entire branch of the UI.
164188

165189
It’s the ultimate optimization: instead of sending the entire blueprint for a skyscraper just to fix a window,
166190
we now send the floor plan for the lobby *and* the specific blueprint for that one window on the 50th floor,

0 commit comments

Comments
 (0)