back

Lazy-Loading Images and Components in Svelte and SvelteKit with Typescript

Introduction

User experience on websites and applications is one if not the most important part that must not be overlooked in the development process. A crucial part of offering an excellent user experience involves making sure your website or application loads quickly and efficiently. Lazy-loading images and components have emerged as a popular methodology to minimize load times and enhance your overall performance. This article focuses on the amalgamation of the progressive JavaScript framework Svelte, along with SvelteKit and Typescript, to implement meticulous lazy-loading. I will walk you through the process, explaining how Svelte and SvelteKit, when combined with the strict syntactical superset of JavaScript, i.e, Typescript, can aid in incorporating the lazy-loading strategy to significantly improve the performance of your web application.

Creating a custom modifier

LazyLoadModifier.ts

  1. Create a new file called LazyLoadModifier.ts in your $lib.
  2. The file should have the following content:
let observer: IntersectionObserver;

function getObserver() {

    if (observer) return;

    observer = new IntersectionObserver(
        (entries: IntersectionObserverEntry[]) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    entry.target.dispatchEvent(new CustomEvent('isVisible'));
                }
            });
        }
    );
}

export default function lazyLoad(element: any) {
    getObserver();
    
    observer.observe(element);

    return {
        destroy() {
            observer.unobserve(element);
        }
    }
}
  1. We are creating a new observer for the element where we will use the modifier. The observer will emit an event called 'isVisible' when the element comes into the users viewport. This will make it easy to trigger the loading process of the element when the user wants to view it and thus 'lazy loading' it!

Using the modifier to lazy load a component

Lazy Loading a Component

To lazy load your component you will have to set up the modifier on the component and define a load function where your data fetching is handled. Once the component comes into the users viewport, we will trigger the async function to load the data and then render the component!

  1. Create your component called Component.svelte.
  2. Create a reactive property called load like so:
// will become true if component comes into viewport
$: load = false;
  1. Create an async function where your data gathering takes place. This is an example where an image is fetched from supabase and the base64 dataUrl is then returned:
async function loadImage() {
  const res = await supabase.storage.from("images").download("image.png");
  return await blobToBase64(res.data!);
}
  1. In the component, add use:lazyLoad and on:isVisible={() => (load = true)} to the outer most html tag and wrap the inside with the content that should be lazy loaded in {#if load}.
<a use:lazyLoad on:isVisible={() => (load = true)}>
  {#if load}
    {#await loadImage()}
        <!--  Add Loading Animation here -->
    {:then data}
      <img src={data} alt="" />
    {/await}
  {/if}
</a>
}

The whole component should look like this:

<script lang = "ts" >
    import type { SupabaseClient } from "@supabase/supabase-js";
    import lazyLoad from "$lib/LazyLoadModifier";
    export let supabase: SupabaseClient;

    $: load = false;

    function blobToBase64(blob: Blob): any {
        return new Promise((resolve, _) => {
            const reader = new FileReader();
            reader.onloadend = () => resolve(reader.result);
            reader.readAsDataURL(blob);
        });
    }

    async function loadImage() {
        const res = await supabase.storage.from("binders").download("image.png");
        return await blobToBase64(res.data!);
    }
</script >

<a use:lazyLoad on:isVisible={() => (load = true)}>
    {#if load}
    {#await loadImage()}
        <!--  Add Loading Animation here -->
    {:then data}
        <img src={data} alt="" />
    {/await}
    {/if}
</a>

Conclusion

Wrapping up, it is undeniable that harnessing the power of Svelte and SvelteKit using Typescript to implement lazy-loading for images and components can vastly boost your website's performance. This not only enhances your user experience but also aids in better SEO rankings due to reduced page load times. By understanding and applying these progressive methodologies in your web development projects, you set yourself up for success in crafting fast and efficient applications. Remember, in the rapidly-evolving digital world, staying updated with the latest strategies like lazy-loading can prove pivotal in taking your web development game to the next level. Get started with Svelte, SvelteKit, and Typescript today, and experience a substantial difference in your application's performance!