Dear @Rich-Harris your work with Svelte is amazing.
I consider you a genius and an innovator like _Leonardo Da Vinci_ or _Henry Ford_.
With Svelte 3 you gave us a bit of that fresh air that we missed for so long.
So first of all I want to give you an immense and melodious thanks.
And now I would like your holy opinion about a doubt, a desire that has gripped me for a long time.
Let's say I have a Svelte 3 SPA (single page application) and a router (svero, navaid, svelte-routing, universal or else).
When I move from one page to another Svelte is very fast, but when there are so many components I feel "the weight", "the slowness" of rendering the entire "page".
If I use the Chrome "Performance" tab > "CPU throttling" > "6x" or "4x" I can see a small, annoying "delay", "lag" before the new page rendering. All this without CSS or JS animations.
"Simply" the page is too full of components that are all needed.
And on those components mounting, there's a lot going on in background (query mostly and computation).
Those components are needed but aren't immediately needed.
What I need immediately _instead_ is the sense of speed of my SPA: to navigate from one page to another (_even if fake, empty_) must be fast!
An example (although not 100%) could be YouTube, which has done a good job on this.
What I'd like to have is:
I tried something like this:
<script>
import { onMount } from "svelte";
import { doQuery } from "../queries";
let canRender = false;
onMount(() => {
setTimeout(() => {
setTimeout(() => {
canRender = true;
});
});
});
</script>
<div>
{#if canRender}
{#await $doQuery}
Loading...
{:then result}
{#each result as player}
<div>{player.name}</div>
{:else}
No player
{/each}
{/await}
{:else}
Loading...
{/if}
</div>
I tried also with tick:
<script>
import { onMount, tick } from "svelte";
import { doQuery } from "../queries";
let canRender = false;
onMount(async () => {
await tick();
canRender = true;
});
</script>
<div>
{#if canRender}
{#await $doQuery}
Loading...
{:then result}
{#each result as player}
<div>{player.name}</div>
{:else}
No player
{/each}
{/await}
{:else}
Loading...
{/if}
</div>
But I don't know if I'm doing well.
And maybe now the problem is just "a tick" away from the first render and then all the renderings happen together at the same time again (am I wrong?).
Since Svelte is perfect I think there might be another different way to deal with this.
I read about:
Since your brain is among the most prosperous in the world, do you think it's possible to introduce something like an "idle-task-rendering-automagically-queue-for-components-and-navigation" in Svelte?
I obviously propose myself as an undying and immediate beta-tester and wiki-docs-writer.
Thanks again for your commitment.
This message is also addressed to people of very high value like @timhall, @jacwright and @lukeed.
Something wonderful can come from your minds.
Thanks to you too for all your wonderful work.
@frederikhors I have created a demo about using IUU pattern with svelte: svelte-idle-until-urgent
@s0kil how can we measure numerically the benefit of idle-until-urgent in your example?
@s0kil thanks for your hint. I'm back on this after long time.
Is idle-until-urgent today still a thing?
Is there any new APIs that we need to be aware of?
@frederikhors for rendering performance, I recommend using requestAnimationFrame rather than setTimeout.
You could create a function that will return a promise to resolve after the given number of animation frames and allow certain pieces of the page to show at frame 1, 2, 3, etc.
export async function awaitFrames(count) {
for (let i = 0; i < count; i++) {
await frame();
}
}
function frame() {
return new Promise(resolve => {
requestAnimtionFrame(resolve);
});
}
<script>
import { onMount } from "svelte";
import { awaitFrames } from "./frames";
onMount(async () => {
await awaitFrames(2);
canRender = true;
});
</script>
@jacwright thanks.
I'm using something like this right now.
I'm not very happy because it seems very hacky to me.
Do you know any packages?
It would be great to have something native already in Svelte or even in browsers.
@jacwright is the below code equivalent?
return new Promise(requestAnimationFrame);
return new Promise(resolve => {
requestAnimtionFrame(resolve);
});
@frederikhors yes, I like that.
Closing as this sounds like something that would be fixed in the user's app rather than Svelte itself. Happy to re-open if I'm incorrect.
@antony this is something even Rich has in mind to address in a future.
I know it can be done in my own apps, but everything can be done in my apps: Svelte is a great toolbox for things like this and it would be amazing to just have it ready inside.
Please can you re-open?
I think we might consider re-raising it as a clear enhancement, as this issue is a bit of a question, but will leave open for now.
This is similar to what I thought: https://github.com/trambarhq/relaks.
It's for React / Preact and I only found out today.
This is their router: https://github.com/trambarhq/relaks-route-manager.
Look at Trambar demo. Amazing smooth navigation between routes!
I opened an issue for svelte-spa-router.
Most helpful comment
I think we might consider re-raising it as a clear enhancement, as this issue is a bit of a question, but will leave open for now.