You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<scriptlang="ts">importtype{PageProps}from'./$types';importProfilefrom"$lib/components/profile.svelte";
let { data }: PageProps=$props();letresponse=$derived(data.response);</script><!-- dummy code for demonstration, this is CSR-only fetching --><svelte:boundary><p>{(await response).ok.user.display_name}</p>
{#snippet pending()}
<p>Loading...</p>
{/snippet}
</svelte:boundary>
In short, desired behavior is:
When user first visits website, for example, /profiles/@testuser, the page must NOT display Loading..., data must be instantly available in the returned HTML, so crawlers could see it, e.g. using opengraph protocol like this:
On subsequent navigation, data should be fetched on the client-side, showing user some kind of loading indication (skeleton of target page with shimmer animation, for example)
How can I achieve this?
Approaches I tried
Using <svelte:boundary> with pending snippet - pending snippet makes fetching purely CSR, so data wouldn't be available in returned HTML instantly.
using {#await} blocks - same, data isn't in returned HTML instantly.
Writing this function and wrapping API.makeRequest in it inside the universal load function:
exportasyncfunctionready<T>(v: T): Promise<T>{returnv;}exportasyncfunctionsleep(ms: number): Promise<void>{awaitnewPromise(r=>setTimeout(r,ms));}asyncfunctionslowdown<T>(ms: number,promise: Promise<T>): Promise<T>{awaitsleep(ms);returnawaitpromise;}exportasyncfunctionhybrid<T>(f: ()=>Promise<T>): Promise<Promise<T>>{if(browser){// Artificially slowdown loading in CSR to see if this approach will actually work.returnslowdown(5000,f());}else{returnready(awaitf());}}// +page.tsexportconstload: PageLoad=async({ params, data })=>{constselector=params.sel=="me" ? null : transformSelector(params.sel);constsession=data.session;constresponse=awaithybrid(()=>API.makeRequest({request: "users::get",data: { selector },
session,}));return{ response };};
Still, it acts like it's rendered only on SSR. Additionally, when I add logging in it like this:
asyncfunctionslowdown<T>(ms: number,promise: Promise<T>): Promise<T>{console.debug("client()");awaitsleep(ms);returnawaitpromise;}exportasyncfunctionhybrid<T>(f: ()=>Promise<T>): Promise<Promise<T>>{if(browser){// Artificially slowdown loading in CSR to see if this approach will actually work.returnslowdown(5000,f());}else{console.debug("server()");returnready(awaitf());}}
Console in browser logs client() and my terminal logs server(), so it looks like sveltekit FIRST executes fetch on the server, waits, and THEN calls fetch on the client.
4. Calling await inside the load function - works well, CSR and SSR as expected, but there's no way to animate the process of loading the data, especially with individual skeletons for pages, so user don't see that fetching IS in progress and page isn't just lagging
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Suppose I have route which needs data from some external API.
And +page.svelte:
In short, desired behavior is:
/profiles/@testuser, the page must NOT displayLoading..., data must be instantly available in the returned HTML, so crawlers could see it, e.g. using opengraph protocol like this:How can I achieve this?
Approaches I tried
<svelte:boundary>withpendingsnippet -pendingsnippet makes fetching purely CSR, so data wouldn't be available in returned HTML instantly.{#await}blocks - same, data isn't in returned HTML instantly.API.makeRequestin it inside the universalloadfunction:Still, it acts like it's rendered only on SSR. Additionally, when I add logging in it like this:
Console in browser logs
client()and my terminal logsserver(), so it looks like sveltekit FIRST executes fetch on the server, waits, and THEN calls fetch on the client.4. Calling
awaitinside theloadfunction - works well, CSR and SSR as expected, but there's no way to animate the process of loading the data, especially with individual skeletons for pages, so user don't see that fetching IS in progress and page isn't just laggingBeta Was this translation helpful? Give feedback.
All reactions