SvelteKit 全栈应用:路由、服务端加载与适配

FreeGuideOnline 最新 2026-06-15

SvelteKit 全栈应用入门

SvelteKit 是基于 Svelte 的全栈框架,它统一了前端渲染、后端接口和数据获取的写法。无论你最终目标是静态站点、单页应用(SPA)还是带服务端渲染(SSR)的全栈服务,SvelteKit 都能用同一套项目结构和代码完成。本教程从零开始,聚焦三个核心模块:路由服务端加载适配器

项目初始化

确保 Node.js 版本在 16 以上,然后运行:

npm create svelte@latest my-app
cd my-app
npm install
npm run dev

选择默认模板(Skeleton project),开启 TypeScript 是可选的,但推荐使用。

路由系统深入

SvelteKit 使用文件系统驱动的路由,所有页面文件放在 src/routes 下。路由不仅仅是 URL 匹配,还能定义布局、错误边界和服务器端行为。

基础页面与布局

  • +page.svelte:定义具体页面的 UI 组件。
  • +layout.svelte:定义共享布局,子页面的内容会插入 <slot />

示例:根布局与首页

src/routes/
├ +layout.svelte
├ +page.svelte
└ about/
  └ +page.svelte

+layout.svelte 中写入:

<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
</nav>
<main>
  <slot />
</main>

+page.svelte

<h1>Welcome to My SvelteKit App</h1>

访问 /about 时,会复用相同的导航栏布局。

动态路由与参数

用方括号包裹参数名来创建动态路由:

src/routes/blog/[slug]/
└ +page.svelte

+page.svelte 中可以通过 $page store 拿到参数:

<script>
  import { page } from '$app/stores';
</script>

<h1>Post: {$page.params.slug}</h1>

可选参数与其余路径

  • [[optional]]:可选参数,例如 src/routes/product/[[id]]/+page.svelte 匹配 /product/product/123
  • [...rest]:匹配任意深度路径,如 src/routes/docs/[...path]/+page.svelte 可匹配 /docs/a/b/c

错误页面

每个路由层级都可以有 +error.svelte,用于优雅地展示错误信息。它接收 errorstatus 属性。

<script>
  export let error;
  export let status;
</script>
<h1>{status} Error</h1>
<p>{error.message}</p>

服务端数据加载

SvelteKit 使用 load 函数从服务端或客户端获取页面所需数据,并将其传递给页面组件。有两种类型的 load 文件:

  • +page.server.js仅运行在服务端,可以使用数据库、私密 API 密钥等。
  • +page.js:可能运行在客户端或服务端(取决于场景),适合调用公开 API 或与浏览器相关的操作。

通常优先使用 server load,保证安全与性能。

编写 Server Load 函数

创建 src/routes/blog/+page.server.js

/** @type {import('./$types').PageServerLoad} */
export async function load() {
  // 模拟从数据库获取文章列表
  const posts = [
    { slug: 'hello-world', title: 'Hello World' },
    { slug: 'sveltekit-rocks', title: 'SvelteKit Rocks' }
  ];
  return { posts };
}

在对应的 +page.svelte 中自动接收 data 属性:

<script>
  export let data;
</script>

<h1>Blog</h1>
<ul>
  {#each data.posts as post}
    <li><a href="/blog/{post.slug}">{post.title}</a></li>
  {/each}
</ul>

动态参数与 Server Load

对于 src/routes/blog/[slug]/+page.server.js

/** @type {import('./$types').PageServerLoad} */
export async function load({ params }) {
  // 根据 params.slug 查询数据库
  const post = await getPostBySlug(params.slug);
  if (!post) {
    throw error(404, 'Post not found');
  }
  return { post };
}

使用 SvelteKit 提供的 error 辅助函数可以立即返回错误状态页。

Layout Server Load 与数据共享

布局文件也可以有 +layout.server.js,其返回的数据对所有子页面都可见。例如,在根布局加载当前用户信息:

// src/routes/+layout.server.js
export async function load({ locals }) {
  return {
    user: locals.user
  };
}

然后子页面通过 $page.data.user 或在 +page.svelte 中通过 export let data 访问(data 会自动合并父布局的数据)。

流式加载与 Promises

如果需要先渲染页面框架,再将稍后获取的数据流式传输到页面,可以直接返回 Promise,然后在页面中使用 {#await}

export async function load() {
  return {
    delayedInfo: fetchSlowData() // 返回 Promise
  };
}
{#await data.delayedInfo}
  <p>Loading more info...</p>
{:then info}
  <p>{info}</p>
{/await}

适配器与部署

适配器(Adapter)负责将 SvelteKit 构建产出转换成特定平台需要的格式。一个 SvelteKit 应用可以部署到 Node.js 服务器、无服务器函数、静态文件托管或边缘网络,只需切换适配器即可。

常用适配器

  • @sveltejs/adapter-auto:自动检测目标环境(Vercel、Netlify、Cloudflare Pages 等),适用于零配置部署。
  • @sveltejs/adapter-node:构建为 Node.js 服务端应用,可以部署到任何支持 Node 的主机。
  • @sveltejs/adapter-static:将整个应用预渲染为纯静态文件,适合纯内容站点。
  • @sveltejs/adapter-vercel / adapter-netlify:针对特定平台的优化。

安装与配置

以 Node 适配器为例,安装:

npm i -D @sveltejs/adapter-node

修改 svelte.config.js

import adapter from '@sveltejs/adapter-node';

export default {
  kit: {
    adapter: adapter()
  }
};

运行 npm run build 后,输出会在 build/ 目录下。用 Node 启动:

node build/index.js

静态适配器与预渲染

许多网站只需静态文件。安装 adapter-static,并在 svelte.config.js 中配置:

import adapter from '@sveltejs/adapter-static';

export default {
  kit: {
    adapter: adapter({
      pages: 'build',
      assets: 'build',
      fallback: undefined
    })
  }
};

如果需要完全静态,还需要为想要预渲染的路由添加 +page.js 并设置 export const prerender = true;,或使用根布局的 +layout.js 统一设置。动态路由需要提供 entries 方法或在 svelte.config.js 中实现 prerender.entries

示例:为博客所有文章生成静态页面src/routes/blog/[slug]/+page.js(注意,是 +page.js,可运行在服务端和客户端):

export const prerender = true;

export async function entries() {
  // 获取所有有效的 slug
  const posts = await fetchPosts();
  return posts.map(post => ({ slug: post.slug }));
}

环境变量与运行时

服务端 load 可以通过 process.env$env/static/private 模块访问私密环境变量。SvelteKit 会安全地处理这些变量,不会暴露给客户端。

完整示例:构建一个博客应用

结合所学,我们快速搭建一个博客,包含首页文章列表、文章详情和静态化部署。

1. 路由结构

src/routes/
├ +layout.svelte
├ +layout.server.js   (加载站点配置)
├ +page.svelte         (首页,文章列表)
├ +page.server.js
└ blog/
  └ [slug]/
    ├ +page.svelte
    ├ +page.server.js
    └ +page.js         (用于静态预渲染的 entries 声明)

2. 数据获取模拟 创建 src/lib/posts.js

const posts = [
  { slug: 'sveltekit-intro', title: 'SvelteKit 入门', content: '...' },
  { slug: 'routing-deep-dive', title: '深入路由', content: '...' }
];

export async function getAllPosts() {
  return posts;
}

export async function getPostBySlug(slug) {
  return posts.find(p => p.slug === slug) || null;
}

3. 首页 server load src/routes/+page.server.js

import { getAllPosts } from '$lib/posts';

export async function load() {
  const posts = await getAllPosts();
  return { posts };
}

+page.svelte 循环展示列表。

4. 文章详情 src/routes/blog/[slug]/+page.server.js

import { getPostBySlug } from '$lib/posts';
import { error } from '@sveltejs/kit';

export async function load({ params }) {
  const post = await getPostBySlug(params.slug);
  if (!post) throw error(404, '文章未找到');
  return { post };
}

+page.svelte 展示标题和内容。

5. 预渲染静态版本 src/routes/blog/[slug]/+page.js

import { getAllPosts } from '$lib/posts';

export const prerender = true;

export async function entries() {
  const posts = await getAllPosts();
  return posts.map(p => ({ slug: p.slug }));
}

然后使用 adapter-static 构建,即可得到完全静态的博客站点,可以直接部署到 GitHub Pages 或 CDN。

总结

SvelteKit 的文件路由结构直观且强大,load 函数将数据获取与页面紧耦合,同时通过 server / client 分离保障安全。适配器让同一套代码可以输出不同部署形态,从小型静态站到全栈服务都游刃有余。掌握这些核心概念后,你便可以借助 SvelteKit 快速构建高性能、类型安全的现代 Web 应用。