Search code examples
javascriptsveltespinnerloadingsveltekit

SvelteKit loading animation


I found that sveltekit do load() function in .js file SSR-ly. What i don't like is how they present the page even the load is not fully completed (even with .server.js).

Example weird animation page

enter image description here

I found workaround to hide the page until its fully loading, onMount().

  // Loading Screen
  let isLoading = true
  onMount(() => {
    isLoading = false
  })

After isLoading

enter image description here

Example Implementation

<script>
  // Svelte
  import {onMount} from "svelte"
  import moment from "moment"
  import axios from "axios"

  // Components
  import HomeHeader from "./home/HomeHeader.svelte"
  import HomeNewsMain from "./home/HomeNewsMain.svelte"
  import HomeNewsLatest from "./home/HomeNewsLatest.svelte"
  import HomeCards from "./home/HomeCards.svelte"
  import LoadingFull from "$lib/components/LoadingFull.svelte"
  import Skew_LightGray_White from "$lib/assets/Skew_LightGray_White.png"
  import {GmsStore} from "$lib/stores/GmsStore.js"

  // Navbar
  import {NavbarStore} from "$lib/stores/NavbarStore"
  NavbarStore.set({
    ...$NavbarStore,
    currentTheme: "white",
  })

  // Ads
  import {AdsStore} from "$lib/stores/AdsStore.js"
  AdsStore.set(true)

  // Fetch Data
  export let data

  // Loading Screen
  let isLoading = true
  onMount(() => {
    isLoading = false
  })
</script>

<svelte:head>
  <title
    >{$GmsStore?.title ? `${$GmsStore.title} - ` : ""}{$GmsStore?.header?.home.title
      ? $GmsStore?.header?.home.title
      : ""}
  </title>
  <meta
    name="description"
    content={$GmsStore?.header?.home.desc ? $GmsStore?.header?.home.desc : ""} />
</svelte:head>

{#if !isLoading}
  <main>
    <HomeHeader />
    <HomeNewsMain />
    <HomeNewsLatest data={data.news} />
    <img src={Skew_LightGray_White} class="w-full h-[120px]" />
    <HomeCards />
  </main>
{:else}
  <LoadingFull />
{/if}

Is there any specific way how to handle this? Like how to completely wait the page to be loaded in the Server (like php?)


Solution

  • This is weird, because I don't think this has anything to do with the load function directly. From what I see, the problem is that the nav bar is loading slowly, and then pops out the rest of your page, while the actual element that depends on your load function is visible instantly.

    Does this happen consistently, with every refresh? How about when you click the links above to do client side navigation?

    Btw, a lot of web pages have spinners or placeholders like this, possibly because of the same reason. If you want to have the page appear instantly, and just load the dynamic data on the fly, the only solution I can think of is predendering + dynamic data. I would read this chapter first before doing it, though.

    • In page.js/ts do export const prerender = true
    • Use on mount to load the data instead of showing the spinner
    let data
    
    onMount(async () => {
       data = await fetch(....)
    }
    

    Then, if you npm run build and npm run preview, your page would be rendered as static html, with just that data being dynamic. It's not ideal, but it's the only thing I can think of to do it without a loading spinner if it isn't a caching issue for the css or the fonts you are using (did you disable caching for the browser?).

    Edit: Btw, are you doing something funky in your header svelte component? Can you paste that code as well?