-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
For the purposes of explaining the bug:
Let's say my index.html contains this:
<html>
<body>
<div id="app">
SAMPLE BODY
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>Let's say svelte will manage the app div on the client.
import { mount } from 'svelte'
import AppWrapper from './AppWrapper.svelte'
const app = mount(AppWrapper, {
target: document.getElementById('app')!,
})
export default app- I am trying to do SSR for Svelte on a non-JS programming language server. This is quite challenging.
- My solution is kick-start a JS runtime on my server (eg. v8).
- Run the Svelte code in the server's JS runtime.
- Parse the rendered html output and copy the entire DOM structure within the
appdiv tag. (NB: "SAMPLE BODY" text was just an example, not the real rendered html output. Also that text was not in the index.html file passed to the JS runtime!) - When it's time to serve the actual html file and svelte-generated js file, I replace the contents within the
appdiv tag with the html from step 4. - CSR happens.
- For me, the client-side rendering is the "source-of-truth" and should always be preferred because it is official and not hacky.
The BUG
- For some reason, svelte appends the client-side rendered DOM inside the
apptag instead of replacing it. (i.e. for the example at the top, it will say "SAMPLE BODY" AND THEN the acual client-side rendered DOM. (Note: React replaces instead of appends) - There is also NO hydration_mismatch errors on the console.
Extra Issue in Documentation:
There are 3 relevant errors:
- https://svelte.dev/docs/svelte/runtime-warnings#Client-warnings-hydration_attribute_changed
- https://svelte.dev/docs/svelte/runtime-warnings#Client-warnings-hydration_html_changed
- https://svelte.dev/docs/svelte/runtime-warnings#Client-warnings-hydration_mismatch
The docs state a "hacky" way to force a client-side update:
<script>
let { markup } = $props();
if (typeof window !== 'undefined') {
// stash the value...
const initial = markup;
// unset it...
markup = undefined;
$effect(() => {
// ...and reset after we've mounted
markup = initial;
});
}
</script>
{@html markup}Proposal 1
I propose that there is an option added to the compiler to ALWAYS PREFER CLIENT SIDE RENDERING for scenarios such as mine.
Proposal 2
In the docs, it should clearly state EXACTLY which attributes the below applies to (i.e. what else other than src?)
hydration_attribute_changed:
Certain attributes like src on an
element will not be repaired during hydration, i.e. the server value will be kept.
hydration_html_changed:
If the {@html ...} value changes between the server and the client, it will not be repaired during hydration, i.e. the server value will be kept.
Reproduction
N/A (requires code from another programming language)
Logs
No response
System Info
Latest version of SvelteSeverity
blocking all usage of svelte
Thanks @tanhauhau for your video on hydration.