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