Skip to content

Svelte 5: optimise blocks that are the sole child of an element #10997

Open
@Rich-Harris

Description

@Rich-Harris

Describe the problem

Until recently, we had an optimisation for each blocks that were the sole child of an element — we called these 'controlled' blocks, and we could make it faster to empty them by doing element.textContent = ''.

This optimisation was a casualty of a recent refactor, and should be reinstated. But it shouldn't just apply to each blocks, it should apply to everything — if blocks, components, and so on.

Describe the proposed solution

There are four parts that need to work in concert with each other. Firstly, SSR would ideally not bother creating hydration markers — given something like this....

<div><Foo /></div>

...we could just render the <Foo /> contents directly inside the <div>:

-<div><!--[-->(foo contents)<!--]--></div>
+<div>(foo contents)</div>

Secondly, the client-side component's template would skip the anchor:

-var root = $.template(`<div><!></div>`);
+var root = $.template(`<div />`);

Thirdly, the code that finds the anchor would need to be aware of this situation. The $.anchor function here (name subject to bikeshedding) would a) populate hydrate_nodes with the contents of the <div> during hydration, b) insert an empty text node at the end of the <div> and c) return that empty text node to use as the anchor for <Foo />:

var div = root();
-var node = $.child(div);
+var node = $.anchor(div);

Foo(node, {});

Fourthly, in cases like if/each/etc blocks, we can apply the textContent optimisation. But we need to do it carefully — it can only be used when there are no out transitions (excluding local transitions inside child blocks). After clearing the content, the anchor needs to be put back.

This optimisation part, even though it's the main reason for doing this, can be done separately — it probably makes sense to just focus on the hydration stuff first.

I'm not sure 'controlled' is the ideal name for this — it implies something different to me. I'm not sure what the best name would be to describe 'thing that is the only child of an element' — oneling is a word that means 'only child' though it's in somewhat rare usage; 'solo block' or 'standalone block' could work.

Importance

nice to have

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions