Skip to content

OPTION TO PREFER CLIENT SIDE RENDERING (HYDRATION MISMATCH) #14909

@pjebs

Description

@pjebs

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
  1. I am trying to do SSR for Svelte on a non-JS programming language server. This is quite challenging.
  2. My solution is kick-start a JS runtime on my server (eg. v8).
  3. Run the Svelte code in the server's JS runtime.
  4. Parse the rendered html output and copy the entire DOM structure within the app div 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!)
  5. When it's time to serve the actual html file and svelte-generated js file, I replace the contents within the app div tag with the html from step 4.
  6. CSR happens.
  7. 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

  1. For some reason, svelte appends the client-side rendered DOM inside the app tag 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)
  2. There is also NO hydration_mismatch errors on the console.

Extra Issue in Documentation:

There are 3 relevant errors:

  1. https://svelte.dev/docs/svelte/runtime-warnings#Client-warnings-hydration_attribute_changed
  2. https://svelte.dev/docs/svelte/runtime-warnings#Client-warnings-hydration_html_changed
  3. 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 Svelte

Severity

blocking all usage of svelte

Thanks @tanhauhau for your video on hydration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions