Skip to content
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

Hydration warning on console for svelte 5 #95

Open
shamscorner opened this issue Sep 4, 2024 · 26 comments
Open

Hydration warning on console for svelte 5 #95

shamscorner opened this issue Sep 4, 2024 · 26 comments

Comments

@shamscorner
Copy link

shamscorner commented Sep 4, 2024

Describe the bug

Getting hydration issue for svelte 5 project. I just upgraded to svelte 5 on sveltekit project.

Reproduction

Upgrade the svelte version to 5 and having this issue.

Logs

svelte] hydration_html_changedThe value of an {@html ...} block in node_modules/​.pnpm/​[email protected][email protected]/​node_modules/​mode-watcher/​dist/​mode-watcher.svelte changed between server and client renders. The client value will be ignored in favour of the server value

System Info

System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 85.53 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node
    npm: 10.5.2 - ~/.nvm/versions/node/v20.11.0/bin/npm
    pnpm: 9.9.0 - ~/Library/pnpm/pnpm
    bun: 1.0.0 - ~/.bun/bin/bun
  Browsers:
    Brave Browser: 126.1.67.134
    Chrome: 128.0.6613.119
    Safari: 17.6
  npmPackages:
    @sveltejs/kit: ^2.5.24 => 2.5.24 
    mode-watcher: ^0.4.1 => 0.4.1 
    svelte: ^5.0.0-next.233 => 5.0.0-next.233

Severity

annoyance

@oluijks
Copy link

oluijks commented Oct 22, 2024

I wrapped the ModeWatcher component in a browser if block, not sure if that's the way to go about it but it seems to work for me...

@bugproof
Copy link

I wrapped the ModeWatcher component in a browser if block, not sure if that's the way to go about it but it seems to work for me...

No. if you're using SvelteKit don't do this. It will cause a blink from light->dark or dark->light on initial page load.

@nikolaydyankov
Copy link

I copied the mode-watcher folder from node_modules to $lib/components to mess around and try to fix it, and the warning disappeared 🤷

@coryvirok
Copy link

I wrapped the ModeWatcher component in a browser if block, not sure if that's the way to go about it but it seems to work for me...

No. if you're using SvelteKit don't do this. It will cause a blink from light->dark or dark->light on initial page load.

Do you have a real/better workaround?

@RickRyan26
Copy link

Still wondering what to do here

@jdgamble555
Copy link
Contributor

According to @huntabyte on discord:

Tbh idek if it’s possible to prevent that warning because there is always going to be a discrepancy for server vs client markup when detecting browser/system color preferences.

  1. I'm just not sure why this wasn't an issue for Svelte 4... I'm guessing Svelte 4 wasn't sophisticated enough to call the error?

Here is the error line:

  1. The solution for Material UI is to use a CSS variable, so I'm not sure how hard that would be to create a PR, considering everything is built on Tailwind?

Maybe together we can solve this :)

J

@RickRyan26
Copy link

Thanks for the research 👍

Unfortunately I'm having trouble wrapping my head around the CSS variable solution

@jdgamble555
Copy link
Contributor

I take it back, yeah I don't think a CSS only solution could work in this case.

Without a cookie based solution in a hook file to persist the dark mode (almost a different thing), I'm wondering if a script tag could be moved outside the component and into the app.html file directly to prevent the warning?

J

@david-plugge
Copy link

That is what i usually do in my projects. Initially Set the Theme with an inline script placed in app.html and handle subsequent changes within the Theme component

@nikolaydyankov
Copy link

nikolaydyankov commented Nov 8, 2024

Should we consider for a second why my warning disappeared when I moved the script from node_modules to $lib? It doesn't make sense to me, but why did it work?

@jdgamble555
Copy link
Contributor

Should we consider for a second why my warning disappeared when I moved the script from node_modules to $lib? It doesn't make sense to me, but why did it work?

Or why it suddenly appeared in Svelte 4.


In /node_modules/mode-watcher/dist/mode-watcher.svelte,

Changing this:

{#if trueNonce}
<!-- eslint-disable-next-line svelte/no-at-html-tags prefer-template -->
{@html `<script nonce=${trueNonce}>(` +
	setInitialMode.toString() +
	`)(` +
	JSON.stringify(initConfig) +
	`);</script>`}
{:else}
<!-- eslint-disable-next-line svelte/no-at-html-tags prefer-template -->
{@html `<script>(` +
	setInitialMode.toString() +
	`)(` +
	JSON.stringify(initConfig) +
	`);</script>`}
{/if}

to this:

<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html `<script${trueNonce ? ` nonce=${trueNonce}` : ''}>(` +
	setInitialMode.toString() +
	`)(` +
	JSON.stringify(initConfig) +
	`);</script>`}

Seems to fix the problem and get rid of the warning.

Should we make a PR?

That being said, I'm not sure if initalConfig would need to run 2x?

J

@ryansobol
Copy link

@jdgamble555 Maybe I'm missing something, but wouldn't the code with the conditional expression produce the exact same thing as the one with the conditional statement? What am I not seeing?

@jdgamble555
Copy link
Contributor

Honestly, no idea the technical difference, but it seems to work. I'm also not sure why there was an error in Svelte 4...

Anyone else tested this to be sure it works?

@thenetwrx
Copy link

Honestly, no idea the technical difference, but it seems to work. I'm also not sure why there was an error in Svelte 4...

Anyone else tested this to be sure it works?

your fix works perfect for me. i ran into this exact same issue

@jdgamble555
Copy link
Contributor

@huntabyte - Could we get this updated (as long as you see nothing wrong with it) ?

Thanks!

J

@huntabyte
Copy link
Member

Is this warning only happening to you all running Svelte 5? I'm in the process of working on the Svelte 5 version of mode-watcher so I'd prefer to handle this along with the hooks.server related helpers in the @next release.

@huntabyte
Copy link
Member

In the meantime, if someone wants to submit a PR to get this addressed in main, I'm more than happy to review/merge

@jdgamble555
Copy link
Contributor

Yes, this happens for Svelte 5 users. This should hopefully temporarily solve the problem until the runes version.

#99

J

@coryvirok
Copy link

Is this temp fix working for folks? I'm still seeing the warning after upgrading to 0.5.0:

[svelte] hydration_html_changedThe value of an `{@html ...}` block in ./​node_modules/​.pnpm/​[email protected][email protected]/​node_modules/​mode-watcher/​dist/​mode-watcher-full.svelte changed between server and client renders. The client value will be ignored in favour of the server value

Not a big deal, just wondering...

@huntabyte
Copy link
Member

Are you using light or dark mode on your client? @coryvirok

@coryvirok
Copy link

Are you using light or dark mode on your client? @coryvirok

System for the most part but I just tested with both light and dark and they all show the warning.

@huntabyte
Copy link
Member

My guess as to why this is happening is that the information we use, like system-prefers-mode and user-prefers-mode will be different on the server compared to the client 50% of the time.

To fully prevent possible server/client discrepancies, we'd need to use a cookie and provide a helper to enter the sequence of the hooks.server.ts, which is quite annoying considering everything works as expected but the way Svelte handles this warning turns a non-issue into a "reported" non-issue.

I'll look into workarounds to get this warning to go away, it's just going to degrade the DX of mode-watcher.

@huntabyte huntabyte reopened this Nov 19, 2024
@jdgamble555
Copy link
Contributor

This is crazy to me that this works when it is changed in node_modules but not in production.

The cookies method is the correct way as you said because it ensures the dark mode gets generated on the server, which would match the browser.

However, this was not a problem until Svelte 5 decided to use stricter warnings. which makes you wonder if there is a "hack" or "work-around" in Svelte 5 as well.

onMount is technically a correct way, but then you would get the dreaded flicker. So I wonder if there is a way to edit the code before the component gets mounted in the client.

Perhaps $effect.pre() ?

Side Note: There should also be a hook for logged in users to save the dark mode status to the DB and hydrate it from the server.

J

@huntabyte
Copy link
Member

This is crazy to me that this works when it is changed in node_modules but not in production.

This is strange.

Side Note: There should also be a hook for logged-in users to save the dark mode status to the DB and hydrate it from the server.

Of course 😃

@rzzo
Copy link

rzzo commented Nov 27, 2024

Is this temp fix working for folks? I'm still seeing the warning after upgrading to 0.5.0:

[svelte] hydration_html_changedThe value of an `{@html ...}` block in ./​node_modules/​.pnpm/​[email protected][email protected]/​node_modules/​mode-watcher/​dist/​mode-watcher-full.svelte changed between server and client renders. The client value will be ignored in favour of the server value

Not a big deal, just wondering...

I am also still getting the warning still.

[svelte] hydration_html_changed The value of an {@html ...} block in node_modules/​.pnpm/​[email protected][email protected]/​node_modules/​mode-watcher/​dist/​mode-watcher-full.svelte changed between server and client renders. The client value will be ignored in favour of the server value

@huntabyte
Copy link
Member

It's not an error @rzzo it's a warning

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

No branches or pull requests