-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
feat: improve hydration, claim static html elements using innerHTML instead of deopt to claiming every nodes #7426
Conversation
I thinks this fixes #7226 |
will wait for #7280 |
If we want to use |
hmm.. but sveltekit targets currently <svelte:head>
<meta name="xxx" content="yyy" />
</svelte:head> will ssr render to <meta name="xxx" content="yyy" data-svelte="hash" /> |
oh, yes, right you are. please forgive my sleep deprived comment! though it's probably not a bad idea for SvelteKit to use |
3d1cb3c
to
fbfe910
Compare
3b1064b
to
563fc88
Compare
cd46954
to
c2ed80b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just fyi, it looks like there's a new merge conflict
e1fffb5
to
51af4f6
Compare
51af4f6
to
df216ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't review the code, but I did test it manually and it gets a thumbs up from me.
I tested it on c3.ventures which is written in Svelte. It created 29 instances of data-svelte
, which were removed upon hydration.
The entire page in my test is static content and is prerendered. I was hoping there'd just be one data-svelte
attribute at the top of the page. However, it got broken up by each image since I use an image component backed by vite-imagetools
. Maybe in Svelte 5 we can figure out a way for the compiler to recognize that the image is a const
so it can be inlined. Sadly it looks like Prepack is no longer being worked on.
On this one site, it added 250 bytes of common runtime code, but saved 6524 bytes from my main page reducing the size of that file by over 10%.
Without PR:
-rw-rw-r-- 1 benmccann benmccann 97 Oct 5 14:58 0-30f7245e.js
-rw-rw-r-- 1 benmccann benmccann 89 Oct 5 14:58 1-6591d108.js
-rw-rw-r-- 1 benmccann benmccann 147 Oct 5 14:58 2-352fcf64.js
-rw-rw-r-- 1 benmccann benmccann 10381 Oct 5 14:58 index-af9f9aa3.js
-rw-rw-r-- 1 benmccann benmccann 140 Oct 5 14:58 _page-d86dbbba.js
-rw-rw-r-- 1 benmccann benmccann 1855 Oct 5 14:58 singletons-597a2518.js
-rw-rw-r-- 1 benmccann benmccann 546 Oct 5 15:25 _layout.svelte-a8e218a3.js
-rw-rw-r-- 1 benmccann benmccann 60951 Oct 5 15:25 _page.svelte-6fa880c2.js
With PR:
-rw-rw-r-- 1 benmccann benmccann 97 Oct 5 14:59 0-1343795c.js
-rw-rw-r-- 1 benmccann benmccann 89 Oct 5 14:59 1-f3abefb6.js
-rw-rw-r-- 1 benmccann benmccann 147 Oct 5 14:59 2-1bd10837.js
-rw-rw-r-- 1 benmccann benmccann 10631 Oct 5 14:59 index-f37845c4.js
-rw-rw-r-- 1 benmccann benmccann 140 Oct 5 14:59 _page-d86dbbba.js
-rw-rw-r-- 1 benmccann benmccann 1855 Oct 5 14:59 singletons-7a3df618.js
-rw-rw-r-- 1 benmccann benmccann 546 Oct 5 15:27 _layout.svelte-f0b0e2f3.js
-rw-rw-r-- 1 benmccann benmccann 54427 Oct 5 15:27 _page.svelte-70716db4.js
@@ -1,51 +0,0 @@ | |||
<pre> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ask]
Why did you remove a few tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i've combined them into the test/runtime/samples/*
tests
This is awesome! Very eager for this to be merged :) |
@tanhauhau just a small heads up before our PR bash that there's a merge conflict on this one |
df216ee
to
1a045c8
Compare
…creating-nested-nodes
… the server and client
…ed-nodes' of https://github.com/tanhauhau/svelte into tanhauhau/claim-static-html-tag-without-recreating-nested-nodes
@tanhauhau I reverted the |
meaning right now for static nodes in hydration you would always do this would destroy the SSR-ed html elements, and replace it with the i see u removed some of the tests assertions over here 718a25b that tries to assert the same element instance in hydration test i wonder would it be possible or worthwhile to check if the if (parent.innerHTML !== '...') {
parent.innerHTML = '...';
} |
No, only for
Yes, because the test In general, this got my thinking - shouldn't all the tests in hydrate have
How would we write code that compares dynamic content before replacing it? I don't see how that's possible. |
ok that make sense. anyway, i think the changes looks good to me |
…-recreating-nested-nodes
One thing I'm worried about is that with this change everyt little bit of HTML will have a function hydate_single_node_with_text(node, text) {
if (node.textContent !== text) {
node.textContent = text;
}
}
// .. inside hydration block:
hydate_single_node_with_text(div, 'the text that should appear'); |
I think we come out very far ahead. I ran it on a real site earlier up above (#7426 (review)) and it created 29 instances of It's possible this could be further optimized, but I'm not sure it's worth sinking time into honestly as I'd rather spend time thinking about how to optimize perf for Svelte 5. This PR is still nice as it gives us a good starting point for benchmarking. Anything we come up with for Svelte 5 that's a very different approach like should have to beat this method by a good margin if we want to pursue it. |
Co-authored-by: Ben McCann <[email protected]>
Yeah, but |
Related #7341, #7226
innerHTML
to create static element nodes, however, this is de-optimised, when thehydratable
flag is on.This PR allows the element nodes to be claimed using
innerHTML
. It will create adata-svelte
hash on the element that can be optimised this way, and if thedata-svelte
hash does not match, it will fallback to useinnerHTML
to "fix" the elements.{@html xxx}
is the only child of an element, we "optimised" by settingparent.innerHTML = xxx
on mount, for both CSR and hydration. However, for hydration, this will destroy and recreate existing elements from the SSR.When we have
{@html xxx}
as the only child of an element, we adddata-svelte
hash and only do.innerHTML
if the hash does not match.\s\t\r\n
, CSR collapse them into 1 space element' '
, however SSR maintains the original spaces. this PR fix the consistency by collapsing spaces in SSR into 1 space' '
. since however many space between the sibling elements, as long as they are not within<pre>
or<textarea>
, browser will treat them as only 1 space element. This behavior however can be disabled throughpreserveWhitespace
compiler option.Before submitting the PR, please make sure you do the following
[feat]
,[fix]
,[chore]
, or[docs]
.Tests
npm test
and lint the project withnpm run lint
test/server-side-rendering/samples/{textarea-content,pre-tag,preserve-whitespaces}
intotest/runtime/samples/*