SvelteKit is a next-generation framework based on Svelte, designed for building server-side rendered (SSR) and static site generated (SSG) applications. Svelte is a lightweight frontend framework known for its exceptional performance and concise code. SvelteKit extends Svelte’s capabilities, providing a complete development workflow, including routing, data fetching, API calls, and server-side rendering.
Svelte Components
SvelteKit applications are built on Svelte components, which are reusable UI blocks. A typical Svelte component includes three main sections:
-
<script>
tag: Defines component state, logic, and module imports. -
<style>
tag: Specifies private styles scoped to the component, preventing leakage to other components. - HTML or Svelte syntax: Defines the component’s template, determining what is rendered.
Here’s an example of a simple Svelte component, Hello.svelte
:
<script>
// Define component state
let name = 'World';
// Export variables as component props
export let greeting = 'Hello';
</script>
<!-- HTML/Svelte template -->
<h1>{greeting}, {name}!</h1>
<style>
/* Private component styles */
h1 {
color: blue;
}
</style>
Reactive Variables
In the <script>
tag, variables are reactive by default. Svelte automatically tracks changes and updates the view when they occur. In the example above, name
and greeting
are reactive.
Exported Props
Using the export
keyword, variables can be exposed as component props, allowing parent components to pass values. In the example, greeting
is an exportable prop.
Computed Properties and Methods
Svelte supports computed properties and methods in the <script>
tag, calculated based on reactive variables:
<script>
let count = 0;
$: doubledCount = count * 2;
function increment() {
count += 1;
}
</script>
<button on:click={increment}>{count} or {doubledCount}</button>
Conditional Rendering and Loops
Svelte supports conditional rendering (if
and else
) and loops (each
) for dynamic content:
{#if showing}
<p>Visible content</p>
{:else}
<p>Hidden content</p>
{/if}
{#each items as item}
<div>{item.name}</div>
{/each}
Event Handling
Svelte uses the on:
prefix to listen for and handle DOM events:
<button on:click={handleClick}>Click me</button>
Custom Directives
Svelte provides custom directives like bind:
and use:
to extend component behavior. For example, bind:
enables two-way binding:
<input bind:value={name} />
Lifecycle Hooks
Svelte offers lifecycle functions like onMount
, beforeUpdate
, and onDestroy
for executing code at specific component stages:
<script>
import { onMount, onDestroy } from 'svelte';
let mounted = false;
onMount(() => {
console.log('Component has been mounted');
mounted = true;
});
function cleanup() {
console.log('Component is being destroyed');
}
onDestroy(cleanup);
</script>
Routing
1. Routing Structure
SvelteKit’s routing is tightly coupled with the file system in the src/routes
directory. Each directory or file corresponds to a route:
-
src/routes/index.svelte
: The app’s homepage. -
src/routes/blog/[slug].svelte
: A blog post page, where[slug]
is a dynamic parameter.
2. Static Routes
Static routes map fixed URLs to Svelte components. For example, src/routes/about.svelte
matches the /about
path.
3. Dynamic Routes
Dynamic routes capture URL segments as parameters, denoted by square brackets (e.g., [id]
). In the blog example, [slug]
captures strings like /blog/my-first-post
, passing my-first-post
as the slug
parameter.
Load Function
Each route component can define a load
function to fetch data on the server or client, returning a Promise whose result becomes component props:
<script context="module">
export async function load({ params }) {
const response = await fetch(`/api/posts/${params.slug}`);
const post = await response.json();
return { props: { post } };
}
</script>
<script>
export let post;
</script>
<h1>{post.title}</h1>
<p>{post.content}</p>
4. API Routes
SvelteKit supports API endpoints by creating .js
or .ts
files in src/routes
instead of .svelte
files. For example, src/routes/api/posts.js
handles requests to /api/posts
:
export async function get({ params }) {
const response = await fetch(`https://api.example.com/posts/${params.id}`);
return {
body: await response.json(),
};
}
5. Middleware
SvelteKit allows middleware files, like _middleware.js
in src/routes
, to handle all route requests for tasks like authentication or logging:
export async function handle({ request, resolve }) {
const token = request.headers.get('Authorization');
if (validateToken(token)) {
return resolve(request);
} else {
throw new Error('Unauthorized');
}
}
6. Route Navigation
Use the goto
function for client-side navigation or apply the use:link
action to <a>
tags:
<script>
import { goto } from '$app/navigation';
</script>
<button on:click={() => goto('/about')}>
Go to About Page
</button>
<a href="/about" use:link>Go to About Page</a>
7. Route Parameters and Query Strings
Pass route parameters and query strings with goto
:
<script>
import { goto } from '$app/navigation';
</script>
<button on:click={() => goto('/blog/some-post', { id: 123 })}>
View Post
</button>
Data Fetching
SvelteKit provides a flexible data-fetching mechanism via the load
function, used during SSR, client initialization, and navigation.
1. Load Function
The load
function runs when a page loads, fetching data and returning props for the component:
<script context="module">
export async function load({ page, session }) {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return { props: { data } };
}
</script>
<script>
export let data;
</script>
<ul>
{#each data as item}
<li>{item.name}</li>
{/each}
</ul>
2. Load Function Parameters
-
page
: Contains route information, likepage.params
(dynamic route parameters) andpage.query
(query string parameters). -
session
: Stores user session data, useful for authentication.
3. Separating Client and Server Logic
The load
function can differentiate between client and server logic:
<script context="module">
export async function load({ page, session }) {
let data;
if (import.meta.env.SSR) {
// Server-side logic
} else {
// Client-side logic
}
return { props: { data } };
}
</script>
4. Caching and Redirects
The load
function can return status
, headers
, and redirect
properties to control HTTP responses:
<script context="module">
export async function load({ page }) {
const response = await fetch('https://api.example.com/data');
if (response.status === 401) {
return {
status: 401,
redirect: '/login',
};
}
const data = await response.json();
return { props: { data } };
}
</script>
5. Client-Side Data Updates
The load
function can rerun during navigation or component updates to refresh data, using the page.changed
property:
<script context="module">
export async function load({ page }) {
if (page.changed.query) {
// Query string changed, refetch data
}
// ...
}
</script>
Server-Side Rendering (SSR)
SvelteKit supports SSR by default, rendering full HTML on initial load for better SEO and faster first-paint times. The load
function executes server-side, and the fetched data is rendered into HTML.
Static Site Generation (SSG)
SvelteKit supports SSG for prerendering static HTML pages. Running svelte-kit build
in production generates a static site deployable to any static hosting service.
API Routes
Beyond page routes, SvelteKit supports API routes via .js
or .ts
files in src/routes
. For example, src/routes/api/data.js
handles /api/data
requests:
export async function get(request) {
const response = await fetch('https://api.example.com/data');
return {
body: await response.json(),
};
}
Authentication and Middleware
Reusable middleware can be written in the src/lib
directory, running at different stages of the request lifecycle. For example, an authentication middleware:
// src/lib/auth.js
export function authenticate(req, res, next) {
const token = req.headers.authorization || '';
if (validateToken(token)) {
next();
} else {
res.status(401).end();
}
}
Use it in src/routes/_middleware.js
:
import { authenticate } from '../lib/auth.js';
export function handle({ request, resolve }) {
authenticate(request);
return resolve(request);
}
Deployment and Configuration
SvelteKit offers flexible deployment options for platforms like Vercel, Netlify, or AWS Amplify. Configure the target platform using adapters:
// svelte.config.js
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
adapter: adapter(),
},
};
Page Transitions
SvelteKit supports smooth page transitions using the <transition>
and <route>
components within <svelte:head>
:
<svelte:head>
<script>
import { crossfade } from 'svelte/transition';
export let data;
export let component;
let transition;
$: transition = component ? crossfade : null;
</script>
{#if transition}
<transition
bind:this={transition}
duration={300}
outDuration={200}
in={component !== data.component}
out={component === data.component}
>
<slot />
</transition>
{:else}
<slot />
{/if}
</svelte:head>
This code implements a crossfade transition, smoothly fading between pages when the component changes.
Client-Side Routing and Navigation
Use the goto
function or $navigate
store for client-side navigation, or apply the use:link
action to <a>
tags:
<script>
import { navigate } from '$app/navigation';
function handleClick() {
navigate('/another-page');
}
</script>
<button on:click={handleClick}>Go to Another Page</button>
<a href="/another-page" use:link>Another Page</a>
Adapters
Adapters allow SvelteKit apps to be packaged for specific platforms. For example, @sveltejs/adapter-node
targets Node.js servers, while @sveltejs/adapter-static
generates static sites.
Service Workers and Offline Support
SvelteKit supports Progressive Web App (PWA) features, including offline support, via the @sveltejs/adapter-workbox
adapter, enabling service workers for basic functionality without a network.
Static Asset Handling
SvelteKit automatically handles static assets like images, CSS, and JavaScript. Place files in the static
directory, and SvelteKit copies and references them during the build. For example, static/images/logo.png
is accessible at /images/logo.png
.
Environment Variables and Configuration
SvelteKit supports environment variables for different environments (e.g., development, production). Define them in .env
files or svelte.config.js
and access them via import.meta.env
:
// svelte.config.js
export default {
kit: {
vite: {
define: {
'process.env.API_KEY': JSON.stringify(process.env.API_KEY),
},
},
},
};
<script>
console.log(import.meta.env.VITE_API_KEY);
</script>
Type Safety and TypeScript Support
SvelteKit fully supports TypeScript for type safety. Rename .svelte
files to .svelte.ts
and configure TypeScript to enable type hints and error checking.
SvelteKit combines tools for building high-performance SSR applications with an excellent developer experience, flexibility, and ease of use, making it a powerful choice for modern web development.
🚀 Join my technical exchange group to get daily useful information:
Top comments (0)