SvelteKit bears many similarities to Sapper, but adds some new and ambitious features. In particular, SvelteKit allows for targeting different production environments, including serverless environments. SvelteKit also adopts Vite as its dev-time tool, which leverages ES Modules for fast, fine-grained HMR (hot module replacement) during development.
Read on for a preview of SvelteKit, which is nearing its 1.0 release.
The fundamental idea behind SvelteKit is to streamline the entire stack of the application into a single, standardized, file-based layout. This layout is then used to provide a consistent development experience for multiple production environments.
Let’s begin a new SvelteKit project to get a concrete sense of what this means.
On the command line, type the commands seen in Listing 1 to create a new project.
Listing 1. Starting a new SvelteKit project
npm init svelte@next test
npm run dev
You’ll see that when you run the
init command, an interactive dialog gives you the choice between the demo app and a skeleton app. Let’s use the demo app for our tour. Accept the other defaults.
cd into the
/test directory and run
npm run dev, the dev server will start up and you can visit the demo app at
localhost:3000. You’ll see something like Figure 1.
Leave the app running. In another window, take a look at the contents of what has been created. You’ll see that a typical Node/npm-based app layout is in the root directory, including
Alongside these are some SvelteKit specifics:
sveltekit.config.js and the
sveltekit.config.js file is very short to start off, but it is where you can configure some very powerful features. The
/static directory is where static assets like images go. The heart of the application is found in
SvelteKit /src directory
Take a look inside
/src. There you will find several standard files including
hooks.js (for defining cross-cutting code that executes on every request) and
app.html (which bootstraps the front end). You don’t need to worry about those right now.
SvelteKit /src/routes directory
The centerpiece of your new app is contained in the
/src/routes directory. Open
/src/routes, and you’ll see several files and a directory. Let’s take each in turn.
about.svelte: This is a front-end route, corresponding to the page currently hosted at
localhost:3000/about. This demonstrates the basic concept of file-system-based front-end routes.
index.svelte: By convention, this front-end route corresponds to the root URL,
__layout.svelte: This is a special file that defines the shared layout to be applied to all pages. If you open it, you’ll see the
Slotcomponent. This is where the page contents will be inserted.
/todos: This directory contains the content that drives the
/todos, you’ll find the following files:
_api.js: In SvelteKit, files prepended with the underscore character are not routes. Instead, they are used by you, the developer, as internal modules. You can see this file exports a JS module that is used elsewhere.
index.svelte: You’ve seen that this applies to an empty URL path, and it works for nested directories as well. Therefore, this file corresponds to the
index.json.js: This is a back-end route. It follows the same convention as the front-end routes, and therefore provides the content of
localhost:3000/todos.json. If you create some todos, you’ll see the JSON output for them here. That JSON is used by the front-end routes. In short, it provides a RESTful API.
[uid].json.js: This seemingly strange syntax allows for URL path parameters. The token inside the square brackets is made available to the code in this route. In this case, the code uses the
uidvariable to refer to the todo UID being worked upon.
A few general comments: First, each front-end route is defined by those routes with the
.svelte extension, and each of these pages is a Svelte component that builds that page. Second, every back-end route is a file with a
Front-end routes are standard Svelte components, with all the power those entail, including the ability to compose sophisticated nested component-based layouts. Back-end routes are very similar in their APIs to Express endpoints, but they are not exactly the same. Remember that SvelteKit allows you to export your app to a number of production runtimes. Node.js is just one of them.
Because SvelteKit can target multiple environments, the back-end files are a kind of idealized API that can be readily transformed into actual concrete implementations within host environments.
This is accomplished via adaptors, of which there are several official adaptors and a number of community adaptors. And there’s nothing (except time and will) to prevent you building your own adaptor.
You can see that several adaptors target serverless environments like Cloudflare Workers and Vercel, and there are two “standard” adaptors for Node.js and static websites. Note that the Static adaptor means just that: It outputs a non-dynamic website.
Server-side rendering and SPAs
That summarizes the most fundamental concepts in a SvelteKit app, but it just scratches the surface of what SvelteKit is capable of. In particular, SvelteKit is a SSR (server-side rendering) framework. What that means is that the first client-side page component will (by default) be rendered on the server and delivered fully-realized to the browser. Thereafter, the pages will be loaded SPA-style (single-page app) as client-side rendered components.
This drives performance and SEO benefits (similar to Next.js), and means that your pages must be written so as to run both on the server and the client.
In practice, that means that the Svelte components must not rely on client-side-only features (like the
window object). There are ways around this, however, including the ability to detect when the page is being rendered on the browser.
Furthermore, this means that the pages can access remote APIs from both the server and the client (via the SvelteKit
fetch function, a drop-in replacement for the standard browser fetch API).
SvelteKit load() function
Finally, the isomorphic nature of SvelteKit pages means they have the superpower of pre-running data store access. This is seen in Next.js as
getServerSideProps. In SvelteKit, this access is handled via the
load function, which can be exported by pages. (SvelteKit’s
load is similar to Sapper’s
load function exported by pages in SvelteKit is a unique approach to handling data loading in SSR. You can think of it as a special server-side code block that provides data to the page before it is rendered. Consider the load function exported by
/src/routes/todos/index.svelte in Listing 2.
Listing 2. Todo load function
Notice the function is provided via argument with a special
fetch function. This
fetch function has the same API as the standard one you are familiar with from the browser, but allows SvelteKit to run it on the server as well.
Notice also that the
load function returns a value. These values are automatically exposed to the page when it is rendering. In this case, that is either the set of todos or an error message, if something went awry.
A next-gen Next.js
Although SvelteKit owes a debt of inspiration to Next.js, it is definitely a next-generation framework that takes on more ambitious aims, in particular the ability to output production builds to different environments.
SvelteKit gives you all the benefits of Svelte itself, along with a multitude of end-to-end features for building dynamic, data-driven apps.
Matthew Tyson is a founder of Dark Horse Group, Inc. He believes in people-first technology. When not playing guitar, Matt explores the backcountry and the philosophical hinterlands. He has written for JavaWorld since 2007.
Copyright © 2021 IDG Communications, Inc.