SvelteKit入门 #
一、SvelteKit 概述 #
SvelteKit 是 Svelte 的官方全栈框架,用于构建高性能的 Web 应用。
text
┌─────────────────────────────────────────────────────────────┐
│ SvelteKit 架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Svelte 组件 + 客户端路由 + 水合 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↕ │
│ 服务端 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 服务端渲染 + API 路由 + 数据加载 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 特性 │
│ ├── 文件系统路由 │
│ ├── 服务端渲染 (SSR) │
│ ├── 静态站点生成 (SSG) │
│ ├── API 路由 │
│ ├── TypeScript 支持 │
│ └── 零配置部署 │
│ │
└─────────────────────────────────────────────────────────────┘
二、创建项目 #
2.1 初始化项目 #
bash
npm create svelte@latest my-app
cd my-app
npm install
npm run dev
2.2 创建选项 #
text
? Which Svelte app template?
❯ Skeleton project 最小模板
Skeleton project (TypeScript) TypeScript模板
Library 库项目
? Add type checking with TypeScript?
❯ Yes, using TypeScript syntax
Yes, using JSDoc comments
No
? Select additional options
◉ Add ESLint for code linting
◉ Add Prettier for code formatting
◉ Add Playwright for browser testing
◉ Add Vitest for unit testing
2.3 项目结构 #
text
my-app/
├── src/
│ ├── lib/ 共享组件和工具
│ │ └── components/
│ ├── routes/ 路由目录
│ │ ├── +page.svelte 页面组件
│ │ ├── +page.ts 数据加载
│ │ ├── +layout.svelte 布局组件
│ │ └── +error.svelte 错误页面
│ ├── app.html HTML模板
│ └── app.css 全局样式
├── static/ 静态资源
├── svelte.config.js Svelte配置
├── vite.config.ts Vite配置
└── package.json
三、路由系统 #
3.1 文件系统路由 #
text
routes/
├── +page.svelte → /
├── about/
│ └── +page.svelte → /about
├── blog/
│ ├── +page.svelte → /blog
│ └── [slug]/
│ └── +page.svelte → /blog/:slug
└── api/
└── users/
└── +server.ts → /api/users
3.2 页面组件 #
src/routes/+page.svelte:
svelte
<script>
let { data } = $props();
</script>
<h1>Home Page</h1>
<p>{data.message}</p>
3.3 数据加载 #
src/routes/+page.ts:
typescript
export async function load({ fetch }) {
const response = await fetch('/api/data');
const data = await response.json();
return {
message: data.message
};
}
3.4 动态路由 #
src/routes/blog/[slug]/+page.svelte:
svelte
<script>
let { data } = $props();
</script>
<h1>{data.post.title}</h1>
<p>{data.post.content}</p>
src/routes/blog/[slug]/+page.ts:
typescript
export async function load({ params }) {
const { slug } = params;
const response = await fetch(`/api/posts/${slug}`);
const post = await response.json();
return { post };
}
四、布局系统 #
4.1 根布局 #
src/routes/+layout.svelte:
svelte
<script>
let { children } = $props();
</script>
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/blog">Blog</a>
</nav>
</header>
<main>
{@render children()}
</main>
<footer>
<p>© 2024 My App</p>
</footer>
4.2 嵌套布局 #
src/routes/blog/+layout.svelte:
svelte
<script>
let { children, data } = $props();
</script>
<aside>
<h3>Categories</h3>
<ul>
{#each data.categories as category}
<li><a href="/blog?category={category}">{category}</a></li>
{/each}
</ul>
</aside>
<article>
{@render children()}
</article>
4.3 布局数据 #
src/routes/+layout.ts:
typescript
export async function load() {
return {
siteName: 'My Blog',
categories: ['Tech', 'Life', 'Travel']
};
}
五、页面选项 #
5.1 CSR/SSR 配置 #
src/routes/+page.ts:
typescript
export const ssr = true; // 启用服务端渲染
export const csr = true; // 启用客户端路由
export const prerender = true; // 预渲染为静态页面
export const trailingSlash = 'always'; // URL 斜杠
5.2 静态生成 #
src/routes/about/+page.ts:
typescript
export const prerender = true;
export async function load() {
return {
title: 'About Us',
content: 'This is a static page.'
};
}
5.3 服务端专属 #
src/routes/admin/+page.ts:
typescript
export const ssr = true;
export const csr = false;
export async function load({ cookies }) {
const session = cookies.get('session');
if (!session) {
throw redirect(302, '/login');
}
return { session };
}
六、错误处理 #
6.1 错误页面 #
src/routes/+error.svelte:
svelte
<script>
import { page } from '$app/stores';
</script>
<h1>{$page.status}: {$page.error?.message}</h1>
{#if $page.status === 404}
<p>Page not found</p>
{:else if $page.status === 500}
<p>Internal server error</p>
{/if}
<a href="/">Go Home</a>
6.2 抛出错误 #
src/routes/+page.ts:
typescript
import { error } from '@sveltejs/kit';
export async function load({ params }) {
const response = await fetch(`/api/posts/${params.slug}`);
if (!response.ok) {
throw error(response.status, 'Post not found');
}
const post = await response.json();
return { post };
}
6.3 重定向 #
src/routes/+page.ts:
typescript
import { redirect } from '@sveltejs/kit';
export async function load({ cookies }) {
const session = cookies.get('session');
if (!session) {
throw redirect(302, '/login');
}
return { session };
}
七、表单处理 #
7.1 表单 Actions #
src/routes/login/+page.svelte:
svelte
<script>
let { form } = $props();
</script>
<form method="POST" action="?/login">
<input type="email" name="email" required />
<input type="password" name="password" required />
{#if form?.error}
<p class="error">{form.error}</p>
{/if}
<button type="submit">Login</button>
</form>
src/routes/login/+page.server.ts:
typescript
import { fail, redirect } from '@sveltejs/kit';
export const actions = {
login: async ({ request, cookies }) => {
const data = await request.formData();
const email = data.get('email');
const password = data.get('password');
if (!email || !password) {
return fail(400, { error: 'Email and password required' });
}
// 验证用户
const user = await verifyUser(email, password);
if (!user) {
return fail(401, { error: 'Invalid credentials' });
}
cookies.set('session', user.token, {
path: '/',
httpOnly: true,
secure: true
});
throw redirect(302, '/dashboard');
}
};
7.2 增强表单 #
svelte
<script>
import { enhance } from '$app/forms';
let { form } = $props();
</script>
<form method="POST" use:enhance>
<input type="text" name="name" required />
<button type="submit">Submit</button>
</form>
7.3 自定义增强 #
svelte
<script>
import { enhance } from '$app/forms';
function handleSubmit({ formElement, formData, action, cancel }) {
return async ({ result, update }) => {
if (result.type === 'success') {
console.log('Success!');
}
await update({ reset: false });
};
}
</script>
<form method="POST" use:enhance={handleSubmit}>
<!-- form fields -->
</form>
八、API 路由 #
8.1 创建 API #
src/routes/api/users/+server.ts:
typescript
import { json } from '@sveltejs/kit';
export async function GET() {
const users = await getUsers();
return json(users);
}
export async function POST({ request }) {
const data = await request.json();
const user = await createUser(data);
return json(user, { status: 201 });
}
8.2 动态 API #
src/routes/api/users/[id]/+server.ts:
typescript
import { json, error } from '@sveltejs/kit';
export async function GET({ params }) {
const user = await getUser(params.id);
if (!user) {
throw error(404, 'User not found');
}
return json(user);
}
export async function PUT({ params, request }) {
const data = await request.json();
const user = await updateUser(params.id, data);
return json(user);
}
export async function DELETE({ params }) {
await deleteUser(params.id);
return new Response(null, { status: 204 });
}
九、部署 #
9.1 适配器配置 #
svelte.config.js:
javascript
import adapter from '@sveltejs/adapter-auto';
export default {
kit: {
adapter: adapter()
}
};
9.2 静态部署 #
bash
npm install @sveltejs/adapter-static
javascript
import adapter from '@sveltejs/adapter-static';
export default {
kit: {
adapter: adapter({
pages: 'build',
assets: 'build',
fallback: 'index.html',
precompress: false
})
}
};
9.3 Node.js 部署 #
bash
npm install @sveltejs/adapter-node
javascript
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
adapter: adapter({
out: 'build',
precompress: true
})
}
};
十、总结 #
| 文件 | 说明 |
|---|---|
+page.svelte |
页面组件 |
+page.ts |
页面数据加载 |
+page.server.ts |
服务端数据加载 |
+layout.svelte |
布局组件 |
+layout.ts |
布局数据 |
+error.svelte |
错误页面 |
+server.ts |
API 路由 |
SvelteKit 要点:
- 文件系统路由自动生成
+page.ts用于数据加载+layout.svelte用于共享布局+server.ts用于 API 路由- 支持表单 Actions
- 多种部署适配器
最后更新:2026-03-28