Search code examples
javascriptnavigationsettimeoutrequestanimationframesvelte

Investigation for a smooth and fast UI, doubts using Svelte 3


Issue

I'm using Svelte 3 and the amazing svelte-spa-router (https://github.com/ItalyPaleAle/svelte-spa-router)!

The question is not intended for exclusive use with this router.

Many projects has heavy pages with heavy scripts.

I need a smooth and fast UI with immediate feedback when I change page.

One possible solution

As you can read here: https://github.com/sveltejs/svelte/issues/2979 about a year ago I asked for something similar to the authors of Svelte.

A few hours ago @jacwright suggested using requestAnimationFrame instead of setTimeout (https://github.com/sveltejs/svelte/issues/2979#issuecomment-587979989).

export async function awaitFrames (count = 1) {
  for (let i = 0; i <= count; i++) {
    await new Promise(requestAnimationFrame)
  }
}
onMount(async () => {
  await awaitFrames(2);
  mySlowFunction(10);
  loaded = true;
});

Question time

I still don't know if this is the best solution for the problem.

  • Is there anything better that can be done?

  • Is requestAnimationFrame the best tool to address this?

Reproduction

Live example: https://codesandbox.io/s/investigation-for-a-fluid-ui-bhknp.

As you can see if you click on:

  1. Light page:

    1. when you click it loads immediately!
  2. Hard page:

    1. when you click the page freeze
    2. slow CPU intensive work goes on and
    3. only after that Svelte renders the page
  3. Hard page with rAF:

    1. when you click the page loads immediately
    2. after that the CPU intensive work begins
    3. after that CPU work the loaded var is set to true

Solution

  • This is not a svelte problem, it is a common problem for all web applications: javascript is single-threaded, when you stress the client with a long-running process, then the user can't use the interface. And, yes, this also holds true when we wrap the long running task in a promise. Should be the same with react or vue and it should also be the same problem when you serve the pages and also send the script to the client.

    So, either avoid long running tasks on the browser or split them in smaller chunks so that the user can still interact with the UI - or use web workers.

    And of course, you can still use a SPA based on svelte (or react or vue) and call API on the backend that does the calculation.