-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Better hydration #4308
Comments
If anyone else is blocked by the iframes ssr/hydration problems or really cares about hydration speed, I'm currently maintaining a fork https://github.com/wix-incubator/wix-svelte which you can use directly just point your package.json |
At the moment this is a major problem on a website I'm working on with Sapper. I opened an issue on Sapper repo. sveltejs/sapper#1088 (@avi I'll try your fork tomorrow and let you know if it worked) |
@avi I just tested your fork on my project (see commit sandrina-p/portfolio_v3@96cfa06) and it worked! Thanks! 😻 |
I'd like to see this improvement absolutely. Currently we're server-side rendering components via node CLI, then hydrating on the client (building a language learning app). Because SSR elements are cleared and re-added it results in the rendered page being displayed, before disappearing to be replaced with a loading message, and then the hydrated page appears. |
Just found this issue after looking around. +1 for this! My specific issue related to this is that it causes Largest Contentful Paint to only be registered after hydration is done, because it removes the DOM node and re-insert it. |
Sorry this PR probably needs to be redone, we've postponed using svelte for
now.
But I'll try to do it later this week, if someone tells me whether to do it
as a compiler flag or a breaking change.
…On Tue, Jun 16, 2020 at 12:42 PM Jacky Efendi ***@***.***> wrote:
Just found this issue after looking around. +1 for this!
My specific issue related to this is that it causes Largest Contentful
Paint <https://web.dev/lcp/> to only be registered after hydration is
done, because it removes the DOM node and re-insert it.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4308 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAQWIOLLPBTVGDH6H3ZCC3RW45ATANCNFSM4KKUK5TQ>
.
|
The problem is that this a breaking change right now and we need to decide if the old way is worth preserving to make migration easier or not. I think it isn’t because right now the diff between doing hydration and cleaning all the SSRed DOM and doing client side render is better than using hydration as is... but that is easy for me to say because we don’t use svelte right now partly because of this issue... I need a decision/guidance from a maintainer... |
This is a deal-breaker for websites that have animations or media autoplay (e.g. audio, videos, gif, etc...) on page load because it would restart them when the CSR is done, as I explained in the issue sveltejs/sapper#1088. |
For what it's worth, I'm leaning towards the idea that client-side rendering (CSR) with a CDN that pushes |
The biggest advantage of hydration is SEO/no-script support if these aren't
important for your use cases a preload + client side rendering might be
better.
If you only care about FMP/LCP/TTI it would depend on the sizes of the
bundles vs resources vs HTML, and that would depend on the specifics of the
project.
You can also probably write this a generic solution for this approach of
preloading assets, which uses a special variant of SSR compiler that only
generates the preload links by finding all resources pointed to in the
HTML. You don't even have to parse HTML strings, except for @html content
and maybe those can be delivered as phase2.
|
This being a breaking change isn't just some theoretical concern - I have a project right now where there's some text related to timezones that might get changed during hydration vs what came from the server. If we want to have something that makes more assumptions about what it's starting with, it would need to be opt-in rather than a default, and ideally it would also be something over which more control can be exerted at compile time, as no one knows better than the application author which bits are safe to assume will already match. I don't know what that new API or component syntax would look like. |
Text node diffs were handled in the PR - but DOM attributes were not - if
the class of an element is different it would change the current behaviour
as the current behaviour is to remove all attributes from every element
claimed and start writing back to them.
I know it is a breaking change, but I believe that people for which this is
a breaking change would be better off by removing all the DOM they got from
SSR, and doing client side render, as it will give better
performance/smaller bundle size, as the affect of removing all attributes
from elements is that everything is recalculated in the browser every
element is tainted and the browser needs to do more work than it does in a
client side render because elements are removed/reattached to the DOM
constantly.
…On Tue, Jun 16, 2020 at 9:22 PM Conduitry ***@***.***> wrote:
This being a breaking change isn't just some theoretical concern - I have
a project right now where there's some text related to timezones that might
get changed during hydration vs what came from the server. If we want to
have something that makes more assumptions about what it's starting with,
it would need to be opt-in rather than a default, and ideally it would also
be something over which more control can be exerted at compile time, as no
one knows better than the application author which bits are safe to assume
will already match. I don't know what that new API or component syntax
would look like.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4308 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAQWIJYF5DDJRDROQLCBADRW6Z5DANCNFSM4KKUK5TQ>
.
|
If I'm not mistaken, in React, when the SSR (server-side render) and CSR (client-side render) don't match, there's a warning in the console about it. Maybe here it could follow the same approach and explain that those types of "diffs" must be fixed. Example: Check the URL to activate an element (by adding a class |
I got a bit more detail from the other maintainers on why this PR has languished. There's an overall feeling that the current approach of repairing the DOM is considered to be a feature not a bug. There are cases it handles that the PR would not such as progressive enhancement of a I know there's been a lack of communication on this PR. We've tried to make a handful of changes to make it easier to discuss changes lately such as setting up |
I don’t mind implementing it as a way to kickstart the discussion unfortunately the discussion part was lacking. I suggested adding the alternative implementation as a compiler flag so users opt-in/out of the new behavior, it would also have been possible to change it so only a specific subtree is repaired for specific cases such as progressive enchantment.
In the meantime we have unfortunately postponed adopting svelte for the current rewrite, not only as a runtime but also as an authoring method because of the typescript support which has been fixed now ( played with compiling svelte to react components so we can work around the hydration problems until this issue is resolved )
I know all the maintainers are busy and have full time jobs other than svelte so I am understanding of the situation, but I feel this was a missed opportunity for the project, as we were looking into investing significant resources to improve the ecosystem
I still hope to use svelte in a future project :)
… On Sep 21, 2020, at 00:03, Ben McCann ***@***.***> wrote:
I got a bit more detail from the other maintainers on why this PR has languished. There's an overall feeling that the current approach of repairing the DOM is considered to be a feature not a bug. There are cases it handles that the PR would not such as progressive enhancement of a select that turns into an autocomplete upon client render. There's also a recognition that the current implementation has performance concerns and edge cases it doesn't handle well (iframes, videos, etc.) and leaves much to be desired. However, I think there's some feeling that we should investigate whether it's possible to create a solution that addresses these shortcoming without losing out on the existing DOM repairing feature.
I know there's been a lack of communication on this PR. We've tried to make a handful of changes to make it easier to discuss changes lately such as setting up #svelte-dev and #contributing channels on Discord and better surfacing the RFC process. The hope is that we can discuss any big changes before they get to the implementation stage to work out the details in the most efficient manner, so please feel to free to find us via those avenues.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Hey, since the topic of this issue is 'Better hydration' and maintainers seem to be investigating the subject, I'll drop my 2 cents on a somewhat perpendicular concern... ^^ It would be nice to have a way to target parts of the DOM for hydration more precisely. For the moment, we can only wipe out everything inside a DOM node. The use case is partial hydration of a component containing multiple top-level elements (that may be side by side with other elements from other components). Partial hydration is a feature that is on everyone's mind when looking at the future of static site generators (SSG) or server side rendering. I am working on an SSG and I have the feature working but it comes with compromises that I would love to be able to avoid, namely the whole component that we want to hydrate with JS needs to be wrapped in an HTML element alone. I have read a few issues regarding this behavior and understand the concern of shipping too much code when it only applies to edge use cases. I am posting this here because I am wondering if there is a better solution for hydrating that does not involve shipping more code. I don't know the ins and outs of hydration with Svelte so I am mainly talking about developer experience here. I am happy to discuss hydration and provide examples of how I use it if it can help bring the discussion forward. :) PS: Another SSG project doing partial hydration with Svelte is ElderJS. I haven't investigated yet if the author managed to workaround the limitations I mention. |
Elder.js maintainer here. You nailed it. Components must be wrapped in a named div so we can target it. The implementation breaks inline, inline-block components (icons for instance), grid components but most of can be fixed with css. The greater problem we’ve faced is the behavior of the CSS being emitted during SSR. If there are any false-y values the css is just excluded. While it makes sense to exclude css that is not relevant when rendering on the client, on the server it makes 0 sense. We’re still trying to find a work around. |
I don't want to get too far off-topic here, but Sapper's CSS handling was recently rewritten and we plan to refactor it out into a separate Rollup plugin in the hopefully not-too-distant future (I'm mainly waiting to have a release or two without any CSS bug reports to make sure things are really working well first). I'm not fully aware of what your issues are, but you might want to watch the Sapper release notes for when that happens. Feel free to ping me on Discord or elsewhere for more details, so that we don't take this off-topic here |
As a temporary solution until hydration is improved I currently disabled SSR+hydration in my project and switched to CSR. I just send the data into a Honestly, there should be huge red warnings in the docs about the current state of hydration in Svelte which seems almost unusable. Makes you wonder if that's the reason why Sapper pushed people into a SPA (and apparently SvelteKit will too). Edit: I was wrong. The JS state is not maintained when going back with CSR. The form values are though. After a long discussion with Rich on Twitter about client-side routing, I have to concede the SSR+hydration approach is less desirable than I initially thought for my use case (backend dashboard). I totally wish hydration was better in Svelte, but if using client-side routing this is definitely much less of an issue. |
Although a bit unrelated but having an option in sveltekit to switch between ssr and this method while preserving all the other features would be great. |
Any open blockers on this? Huge SEO priority as we’ve seen Google is very slow at indexing pages that have large chunks of their content hydrated. To me this points to Gbot waiting for the JS rendering of the page to be done before analyzing the page for quality mainly because the DOM is destroyed and rebuilt. Yes this is speculation but very hard to understand why these pages would be taking so long to be indexed. It is a common theme across several sites. |
Yeah GoogleBot definitely waits for JS execution. A couple of years ago I remember Google made a big deal out of GoogleBot finally being able to execute ES6. There are services that pre-render sites to static HTML specifically for crawlers such as: https://prerender.io/ Google has actually an article with more info about this: https://developers.google.com/search/docs/guides/dynamic-rendering |
I’m definitely familiar. The thing is that we’re SSRing (static exporting) the entire page and partially hydrating 3-4 components. (Elder.js) If a component that is hydrated is above the fold Google delays indexing until the JS bot finishes rendering which takes days to weeks. This isn’t the case with all SSR setups and I believe is unique to Svelte’s poor hydration model that throws out the existing DOM and rebuilds it. |
* Improve SSR hydration performance - Fixes #4308 by avoiding de- and reattaching nodes during hydration - Turns existing append, insert and detach methods into "upserts" The new "hydration mode" was added in order to maintain the detach by default behavior during hydration. By tracking which nodes are claimed during hydration unclaimed nodes can then removed from the DOM at the end of hydration without touching the remaining nodes. Co-authored-by: Jonatan Svennberg <jonatan.svennberg@gmail.com>
Reopening this since the performance improvement had to be reverted (#6290) due to a bug. While reverting we added a test to prevent future regressions. We might be able to get some more tests in by fixing up and merging #4444 If anyone would like to take another stab at getting the performance improvement in, the issue with the original change is described in #6279 (comment) and we'd welcome a PR that improves performance while avoiding that issue. |
@tanhauhau I just happened to stumble upon #3766 today where you said that you're merging consecutive text-a-like nodes. I think there's a good chance that would actually allow us to get the hydration performance fix back in as it was without any additional changes. It was failing when encountering consecutive text-nodes because they were represented as multiple nodes, but would be merged by the browser such that hydration would fail on the client because it was looking for multiple nodes, but they'd been merged. If we're able to get your PR in and we always treat them as a single text node then I think we wouldn't have this issue. |
Sorry if this was answered elsewhere, but has "better hydration" been addressed or has it been abandoned? |
@danawoodman its periodiocally added, then reverted, so its hard to maintain current state :-) |
I believe the primary issue mentioned here (slowness and animation flicker) has been fixed since Svelte 3.38.3 with the #6395 PR. There seems to be some issues to iron out in some edge cases (There were some problems with |
SSR aside of expensive is veeeery slower on my production app, so in the end I've opted to disable SSR globally to have an acceptable performance in my app |
@eriknyk what version of Svelte are you using? I did some SSR benchmarks recently with |
#9662 skips hydration for select attributes and adds a warning in dev mode if the SSR and client-side values are different. This is similar to the idea @avi implemented in #4309, but for a few attributes that are unlikely to differ rather than the entire DOM so that repair still occurs if there are differences elsewhere. Interested users may wish to test that PR or Svelte 5 pre-releases containing the PR after it's merged |
Is your feature request related to a problem? Please describe.
Currently hydration is very expensive, it searches for the correct node type clears it and re-adds the attributes and finally unmounts and remounts the DOM node by calling insertBefore/append
This causes iframes to reload.
In the current implementation setting the innerHTML to '' and doing client side render is faster and cleaner
Describe the solution you'd like
All DOM should be reused, attributes should not be cleared, and no node should be insertBefore/append unless there is an actual reason.
DOM nodes shouldn't be scanned for the correct nodeName - assume everything is in order on the first miss clear all the rest and start adding new nodes as needed
Text nodes need special treatment as they collapse in SSR
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
How important is this feature to you?
It is a deal breaker for us - we have quite a few iframes in use and using hydration in it's current form reloads them, it also slows our TTI. So we are stuck with either using only client-side rendering or picking a different solution
Additional context
The text was updated successfully, but these errors were encountered: