Why are eager fetch()s during SSR warned against?
#16185
RotatingHorse
started this conversation in
General
Replies: 1 comment
|
The warning is about where the SSR data boundary is, not about parallel fetching being bad by itself. Kit's If the goal is to start multiple requests early, put that eagerness in |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Please consider the following code:
If you were a developer that was unfamiliar with Svelte, what would you think this code does?
In my opinion, I think it's fairly intuitive to draw these conclusions:
The page retrieves the user's profile, then displays it if it exists or shows a warning if it doesn't.
The page tries to get the user's profile as soon as possible.
GetProfile()call is at the top level, it should be safe to assume it happens very early when rendering the page.With just this tiny snippet of code, we have a pretty good grasp of what's going on here. There are no runes, and while the
{#if}markup is a little unique, there's not much "magic" happening that requires us to acknowledge the existence of a Svelte compiler.However, if
GetProfile()uses afetch()call (which we rightly dismissed as an implementation detail), by default SvelteKit will put a warning in the console:The warning doesn't stop the above code from working, but it does push developers to move to a different design:
On paper, the code seems to be about the same length — but now we have this mysterious
$props()keyword! What's in$props()? What does it do?To answer that, our unfamiliar-to-Svelte developer will need to 1) read the Svelte documentation, and 2) load the contents of a nearby
+page.server.jsinto their working memory to get the full picture.Without going through the SvelteKit documentation, there's nothing that really connects
+page.server.jsand+page.sveltetogether. It's not like one fileimportsthe other; and if you're using TypeScript with the automatically generated./$types, I'd argue that makes the situation even more awkward. In the end, it's significantly less intuitive and requires more work than being able to look at a well-named function call and almost instantly comprehending the author's intent.There's also the
onMount()option, but I think it's fair to say it doesn't really bring the readability up to the same level as the first example. It also changes the functionality of the code — the above two snippets actually execute thefetch()call during server-side-rendering, allowing users without JavaScript enabled to use the webpage, whileonMount()would practically mandate the inclusion of a placeholder or be forced to drop script-less users entirely.It would be nice if we could write code in the same fashion as the first example, without ever having to dip into the second unless absolutely necessary. But I'm sure there's a reason why we can't do it, otherwise the Svelte maintainers wouldn't have placed a warning. So...why?
Musing: My guess is that it has to do with needing a reactive context, or maybe something related to waterfalls with multiple blocking
awaitcalls. But the latter makes me wonder if something likelet [result1, result2] = await Promise.all([Query1(), Query2()]);at the top level might be ergonomically feasible in cases where the asynchronous work do not depend on each other (if they do, I don't think there's any option besides accepting the waterfall unless you can somehow reverse causality or predict the future, in which case I'd like to throw out there that I would be happy to accept a winning lottery ticket 😄).All reactions