Skip to content

Svelte 5: component hydration not repairing/removing target child elements #10375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jonathonadams opened this issue Feb 2, 2024 · 7 comments · Fixed by #12580
Closed

Svelte 5: component hydration not repairing/removing target child elements #10375

jonathonadams opened this issue Feb 2, 2024 · 7 comments · Fixed by #12580
Milestone

Comments

@jonathonadams
Copy link

jonathonadams commented Feb 2, 2024

Describe the bug

As per the v4 Client API docs, a component can be created with the hydrate: true option to repair and remove existing child elements of the target.

The v5 breaking changes docs state that the compiler option hydratable has bees removed and all components are now hydrated and components are now created with createRoot or mount. Neither of these functions accept hydrate: true as an option.

When using createRoot or mount in v5, child elements of target are left unchanged. The expected behaviour is that of v4 (with hydrate: true) and DOM elements are repaired/removed.

Possibly related

#9827, #10332

Reproduction

minimum repo

Logs

No response

System Info

System:
    OS: macOS 14.1
    CPU: (10) arm64 Apple M2 Pro
    Memory: 66.25 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.9.0 - ~/.local/share/mise/installs/node/20/bin/node
    npm: 10.1.0 - ~/.local/share/mise/installs/node/20/bin/npm
  Browsers:
    Brave Browser: 116.1.57.47
    Chrome: 120.0.6099.71
    Safari: 17.1
  npmPackages:
    svelte: ^5.0.0-next.45 => 4.2.9


### Severity

blocking an upgrade
@dummdidumm dummdidumm added this to the 5.0 milestone Feb 2, 2024
@dummdidumm
Copy link
Member

We will likely adjust this to provide a mount and a hydrate function

@jonathonadams
Copy link
Author

jonathonadams commented Feb 5, 2024

Thanks for the update @dummdidumm.

So as it stands there is no equivalent of v4's new SomeComponent({ target: ....., hydrate: true }) yet? For me it's the glue between htmx and svelte.

Appreciate all the hard work.

@dummdidumm
Copy link
Member

dummdidumm commented Feb 5, 2024

Right now you can just use mount and it will apply the hydration automatically because it detects it. Your reproduction does not work because Svelte 5 uses special comment anchors to find out in which way things need to be hydrated. Is there any reason why you can't server-render the component and use its output? Feels like doing the work twice if you have to maintain a matching dom manually.

@jonathonadams
Copy link
Author

Our app is a Go + htmx setup so server rendering Svelte components is not an option. We use Svelte for isolated, highly interactive parts of the page.

Right now you can just use mount and it will apply the hydration automatically because it detects it.

If I interpret this correctly, it hydrates automatically only if the correct comments exists?

This seems like a big step backwards unless there is a planned API that can hydrate without comments. Adding a requirement to have Svelte specific comments in the markup to enable hydration, were the requirement did not exist previously, seems like this functionality was designed with only SvelteKit in mind.

Again, thanks for all the hard work.

@jonathonadams
Copy link
Author

jonathonadams commented Feb 6, 2024

We will likely adjust this to provide a mount and a hydrate function

I may have skimmed over this, the hydrate function mentioned here, is the intent that this will not require comments like mount?

Edit:
From #10389

When we remove createRoot and introduce hydrate this shouldn't be the case anymore / you'll have more control over it.

Ok, that answers my question. I'll close this as it's working as intended and the missing feature I'm after is incoming. Thanks @dummdidumm

@dummdidumm
Copy link
Member

dummdidumm commented Feb 6, 2024

No I think you misunderstood - the hydrate method will still need comments.

TBH I'm not sure if we can really do something here other than note it in the breaking changes. Keeping the HTML in sync manually is very brittle and Svelte already used hydration comments in a few places for Svelte 4 (for example when using @html or for svelte:head).

By the way - while there is an error logged (it's not thrown, just logged and doesn't stop anything), the app will still be functional. What Svelte does is remove the inner HTML of the target anchor and recreate the DOM nodes from scratch. So the result should be mostly equivalent to the user (edge cases: flickering; you want to preserve certain state which may be reset).

@jonathonadams
Copy link
Author

No I think you misunderstood - the hydrate method will still need comments.

So this is a feature that is being removed in v5 that is currently available in v4? A requirement to have the DOM server rendered by Svelte for hydration to work that was not previously necessary is pretty disappointing.

What Svelte does is remove the inner HTML of the target anchor and recreate the DOM nodes from scratch. So the result should be mostly equivalent to the user (edge cases: flickering; you want to preserve certain state which may be reset).

An example of where we use this is a search autocompletion, with the <input> triggering the completion results. The <input> is server rendered, and may or may not contain some search term depending on where the user navigated from. In Svelte 4 the component can mount without loosing the search term. The requirement for the user to type in their query again is not acceptable for us, and if that is all that svelte 5 has to offer than that might be the deal breaker.

All the above being said, if the decision has been made to require node/Svelte SSR/SvelteKit, then I think there is still a bug irrespective of the lack of hydration. In the minimum repo linked, the innerHTML of target is not removed and the component is just appended after the targets last child. Unless what you described is the intended behaviour of hydrate and not mount

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants