DEV Community

Cover image for Building Progressive Web Applications using SvelteKit
Katerina Braide
Katerina Braide

Posted on

Building Progressive Web Applications using SvelteKit

This article is all about simplifying your path to web development. We will build amazing websites with with SvelteKit, a tool akin to your coding friend. We will quickly set things up, create a basic site with little coding, and easily turn it into a Progressive Web App (PWA).

Introduction to SvelteKit for Building Progressive Web Applications (PWAs)

Svelte, a front-end JavaScript tool, enables the creation and management of user interfaces akin to React and Vue, while SvelteKit serves as a framework. It enhances this potential by offering a framework that enables the development of more comprehensive websites with features such as routing, server-side rendering, and presence of an API. Before its release, developers used a framework known as Sapper for similar purposes. It can thus be considered a consolidated and improved form of sapper. Making comparisons, one may relate SvelteKit to Svelte, Next.js to React, or Nuxt.js to Vue. Svelte primarily focuses on client-side rendering and UI updates in the browser, similar to React or Vue, but it combines server-side rendering with client-side rendering to build fast, high-performance dynamic websites, thereby matching the approach of Next.js and Nuxt.js with React or Vue.

Benefits of using SvelteKit

Using SvelteKit to create websites offers a multitude of benefits.

  • It makes use of both client-side and server-side rendering. As a result, you can receive an HTML page based on your first query to the server. Because it enables page access and full indexing, this is excellent for SEO.
  • The routing system is quite simple, as it utilizes its routing system for handling multiple pages and routing.
  • Since it handles the server side, you can use its API to work with the website's front end.
  • Just like other major JavaScript frameworks, it also makes use of code splitting. This can help increase your application's response time.

As you use most of the popular frameworks, such as React, Vue, or Svelte, while creating web applications, you will notice that most of the time, the result is a single-page application (SPA). This is due to the browser rendering only one HTML page. It could be a blank page. All of this is known as client-side rendering.

With SvelteKit, though, client-side rendering in the browser and server-side rendering mix together. Upon performing a first query to the server, it returns a pre-generated, fully constructed HTML page rather than a blank one. Search engines and site crawlers benefit from this server-side technique because the HTML page sent to the browser already contains content. When users move between pages on the site, Svelte detects requests for new pages, looks at the target pages, and deftly changes content in the browser without further HTML page requests.

These also include server-side rendering and a routing mechanism for pages and components, which improves the idea of a single-page application. Additionally, your application's front end can utilize a custom API to access your server-side logic. We build it on Vite, a front-end tool capable of compiling code and performing hot module replacement. This can allow for live updates in the browser during both code changes and previews.

Project Overview

In this article, we will work on a quote application. When you click a button, this application will randomly render each quote using an external API. We will also use service workers to cache the application and make it available offline for you or your users to use. We will utilize SvelteKit and the quotes API from API Ninjas.

Setting Up Your SvelteKit Project

Now that we have a clear understanding of the project, we can proceed to the primary phase, which involves the project setup. This will contain some installations and configurations. You can follow the steps below.

Installing SvelteKit and setting up a new project

To begin working on the project, you must install the necessary packages. You can use the command:



npm create svelt@latest


Enter fullscreen mode Exit fullscreen mode

You can install the project with all the files and folders, and it will give you the most recent package version of Svelte. You can also follow the steps below to get started:

  • Open a new terminal.
  • Install the necessary packages, files, and folders by running the command:  ```shell

npm generate svelt@latest

* Select the current directory.
* Choose the skeletal template.
* Choose JavaScript.
* Use the handy plugins `eslint` and `prettier`.
* Running `npm install` will help you negotiate into the project and install the necessary modules.
* After setting up the dependencies, use the following command to launch the application:
```shell


npm run dev


Enter fullscreen mode Exit fullscreen mode
  • Visit http://localhost:your-port-number to access the running program on your browser.

Once we complete our project, we will have a wealth of mock code that we can modify to build our intended application.

Configuring SvelteKit for PWA development

Although SvelteKit projects are usually built with Vite and already include a vite.config.js file with appropriate plugins, configuring SvelteKit for PWA (Progressive Web App) development takes a few extra steps beyond the basic project setup with: 



npm create svelt@latest


Enter fullscreen mode Exit fullscreen mode

You can go as follows:

  • Create a custom service-worker.js file within your project's src directory.
  • Service Worker Registration will register the service worker automatically during the building process.
  • Ensure that you have configured your Svelte components to handle PWA features, such as installable app prompts, dynamic caching, and offline support.
  • As necessary, apply service worker registration and cache techniques to your Svelte parts.
  • Build your SvelteKit app using the command: ```shell

npm run build

Once configured, install it in your hosting environment.

Following these guidelines will help you set it up properly for PWA development, allowing features such as [offline capability](https://kit.svelte.dev/docs/service-workers) and better user experiences.

## Building the PWA Features
Acting as a background process inside the browser, a service worker essentially lets JavaScript run in a multi-threaded way. Service workers have many outstanding examples; among them are [Cloudflare workers](https://workers.cloudflare.com/). Cloudflare has turned the web standard for service workers into a JavaScript runtime environment. Tools like [PartyKit](https://www.partykit.io/), which use service workers to subtly load analytics in the background, may be recognizable to you. Service providers provide a wide spectrum of advantages and capabilities; in this case, we will use them to improve our Progressive Web App (PWA).

Create a file named [`+page.svelte`](https://kit.svelte.dev/docs/routing#page); within the file, you must write the code to develop the PWA. We would be building a JavaScript application with quote display capability. The project we will build will retrieve the quotes using an external API. By doing this, you will get many quotes and have a large data set to work with. In your project, all the user has to do is click a button that will fetch and display each quote randomly, making it enjoyable.

```javascript


<script>
    let name = 'World';
    const apiKey = import.meta.env.VITE_API_KEY;

    /**
     * @type {string | null}
     */
    let error = null;

    /**
     * @type {string }
     */
    let title = 'Please click on the button to get a quote.';

    /**
     * @type {boolean}
     */
    let isLoading = false;

    const fetchQuote = async () => {
        try {
            isLoading = true;

            const response = await fetch('https://api.api-ninjas.com/v1/quotes?', {
                headers: { 'x-api-key': apiKey }
            });

            if (!response.ok) {
                error = 'An error ocurred, failed to get quotes.';
                console.log(error);
                return;
            }

            const data = await response.json();
            title = data[0].quote || 'No quote available';
        } catch (err) {
            error = 'An error ocurred, failed to get quotes.';
            console.log(error);
        } finally {
            isLoading = false;
        }
    };
</script>

<div class="index">
    <h1>Hello, {name}</h1>
    <p>
        {#if error}
            {error}
        {:else}
            {title}
        {/if}
    </p>

    <button on:click={fetchQuote}>
        {#if isLoading}
            {'Fetching...'}
        {:else}
            {'Change Quote'}
        {/if}
    </button>
</div>

<style>
    div {
        text-align: center;
        padding: 1em;
        max-width: 240px;
        margin: 0 auto;
    }

    h1 {
        color: #ff3e00;
        text-transform: uppercase;
        font-size: 4em;
        font-weight: 100;
    }

    @media (min-width: 640px) {
        div {
            max-width: none;
        }
    }
</style>


Enter fullscreen mode Exit fullscreen mode

In the code, we made use of an API that will give us data in real-time. The API keys are written in a .env file, so you have to make sure to create one in your project and get your API key, too.

Note: If you are managing your project using a version control system such as git, please do not track the .env file. To ensure that you don't unintentionally reveal your secrets to the public, add .env to your .gitignore file.

Implementing Service Workers for Offline Capabilities

Consider a service worker to be a middleman between your client and servers, capable of handling all requests passed between them. You might have come across mock service workers, which let you test through several situations. Service providers have enormous power that allows a broad spectrum of possibilities. To simplify the use of service workers, SvelteKit requires only the inclusion of a service-worker.js file in the source directory. It automatically handles the registration process, thereby eliminating the need for manual registration that is typically required with other systems. This simplified strategy replaces the need for outside libraries to support this process.

To establish a service worker, go to your project directory, specifically the src folder, and then create your service worker file under service-worker.js. Despite their initial complexity, service providers can simplify into three basic steps:

  • Firstly, you install the service worker, followed by its activation.
  • Secondly, you intercept traffic by listening for fetch events and then substituting the URL with content from the cache, enabling offline functionality. 
  • Thirdly, you can enhance your service worker by allowing communication to notify users of updates, prompting them to reload the page.

Turning on offline mode lets your page run free from an internet connection. If a critical problem necessitates a restart, you can access storage to unregister your service providers. It becomes crucial to monitor the cache storage, as its use triggers the display of cached content.



/// <reference types="@sveltejs/kit" />
import { build, files, version } from '$service-worker';

// Create a unique cache name for this deployment
const CACHE = `cache-${version}`;

const ASSETS = [
    ...build, // the app itself
    ...files // everything in `static`
];

self.addEventListener('install', (event) => {
    // Create a new cache and add all files to it
    async function addFilesToCache() {
        const cache = await caches.open(CACHE);
        await cache.addAll(ASSETS);
    }

    console.log('installing service worker for version', version);
    console.log('caching assets', ASSETS);
    console.log('caching build', build);

    event.waitUntil(addFilesToCache());
});

self.addEventListener('activate', (event) => {
    // Remove previous cached data from disk
    async function deleteOldCaches() {
        for (const key of await caches.keys()) {
            if (key !== CACHE) await caches.delete(key);
        }
    }

    event.waitUntil(deleteOldCaches());
});

self.addEventListener('fetch', (event) => {
    // ignore POST requests etc
    if (event.request.method !== 'GET') return;

    async function respond() {
        const url = new URL(event.request.url);
        const cache = await caches.open(CACHE);

        // `build`/`files` can always be served from the cache
        if (ASSETS.includes(url.pathname)) {
            const response = await cache.match(url.pathname);

            if (response) {
                return response;
            }
        }

        // for everything else, try the network first, but
        // fall back to the cache if we're offline
        try {
            const response = await fetch(event.request);

            // if we're offline, fetch can return a value that is not a Response
            // instead of throwing - and we can't pass this non-Response to respondWith
            if (!(response instanceof Response)) {
                throw new Error('invalid response from fetch');
            }

            if (response.status === 200) {
                cache.put(event.request, response.clone());
            }

            return response;
        } catch (err) {
            const response = await cache.match(event.request);

            if (response) {
                console.log(`Returning from Cache`, event.request.url);
                return response;
            }

            // if there's no cache, then just error out
            // as there is nothing we can do to respond to this request
            throw err;
        }
    }

    event.respondWith(respond());
});


Enter fullscreen mode Exit fullscreen mode

Adding manifest file

When we discuss the manifest, it refers to a document or file that encompasses all the metadata of related files. It includes the title, version, licensing data, and other parts of your project. When building and running projects, this file provides crucial information about the necessary files, assets, and pieces.

Following the steps below, you will be able to add a manifest file to your project.

  • Create a manifest.json file in your project's static directory.
  • Ensure the manifest file contains essential details such as icons, names, and shortcuts for your Progressive Web App (PWA).
  • Link the manifest.json file to your project's src/app.html file.
  • Confirm your service-worker.js file is in your src directory.

Svelte will register the service worker found in the root of the src folder automatically during the build process.
Following these rules will help you easily include a manifest file in your project, allowing PWA functionalities.



{
    "name": "QG",
    "description": "Quote Generator",
    "short_name": "quote",
    "display": "standalone",
    "start_url": "/",
    "background_color": "#808080",
    "theme_color": "#ff3f20",
    "icons": [
        {
            "src": "logo1.avif",
            "sizes": "512x512",
            "type": "image/png",
            "purpose": "any maskable"
        }
    ]
}


Enter fullscreen mode Exit fullscreen mode

The manifest file, which contains the code above, provides information about the name, description, and icon of our project.

Enhancing the PWA with SvelteKit

Improving a Progressive Web App (PWA) means using the features of the framework to improve performance, user experience, and development process simplification. It provides capabilities for responsive design, flawless UI interactions, and effective routing, thereby allowing the creation of dynamic and aesthetically striking PWAs. Developers can improve the functionality and responsiveness of PWAs by using their features for server-side rendering, client-side rendering, and custom API integration, therefore guaranteeing a flawless and immersive experience over several devices. Furthermore, SvelteKit's capabilities include live updates, hot module replacement, and SEO optimization, which help to create high-performance PWAs.

Utilizing SvelteKit's features for responsive design and smooth UI interactions

The framework offers many features that can help improve the design of websites. These features can fit screen widths, providing users with a responsive design and improving their user experience. An important part is that you can also add animations and interactive elements to increase the user experience. This can help provide a user-friendly interface. Since we won't be looking at design in this article, check out this website. They explain how to use Svelte and SvelteKit to create responsive views.

Benefits of building PWAs with SvelteKit

SvelteKit enables one to design Progressive Web Apps (PWAs) with several benefits:

  • Improved Performance: By integrating both client-side and server-side rendering, you can improve the speed of your application.
  • Enhanced SEO: HTML pages being rendered first can help improve search engine optimization (SEO). This can make your project more visible and rank higher when hosted.
  • Adaptive Layouts: Its responsive features make it easier for developers to create responsive designs on different screen sizes.
  • Streamlined Routing Mechanism: Its routing mechanism makes routing straightforward and makes setting up multiple-page routing easier.
  • Personalized API Integration: It also includes the ability to create a custom API for backend logic. You can use this logic on the frontend.
  • Real-Time Updates and Hot Module Replacement: Built on Vue, it provides real-time updates and hot module replacements.

Each feature makes it simple for developers to create progressive web applications (PWAs), which, in turn, improves design, routing, SEO, routing, and workflows.

Image description
The GIF above shows an installable PWA.

Conclusion

This article shows the importance of Progressive Web Apps (PWAs), their comparisons to native apps, and the advantages of employing SvelteKit for PWA development. It is a framework based on Svelte for website construction and includes functionalities such as routing, server-side rendering, and API integration. Using SvelteKit enables one to design Progressive Web Apps (PWAs) with different benefits, such as combining client-side and server-side rendering speed, loading time, and improved performance. Hence, the first rendering phase becomes more user-friendly.

References

Top comments (4)

Collapse
 
manuelco profile image
Nweke Emmanuel

Nice :)

Collapse
 
azubuikeduru profile image
Azubuike Duru

This is real work. Thanks for sharing

Collapse
 
legationpro profile image
Anze

Thanks for sharing! Have you used Next.js before?

Collapse
 
braide profile image
Katerina Braide

Not yet.