Adapter 体系
什么是 Adapter?
SvelteKit 的 Adapter(适配器)是构建输出的转换层——它将 SvelteKit 构建产物转换为特定平台能运行的格式。一套代码,通过更换 Adapter 即可部署到不同的运行环境:
adapter-auto
自动检测部署平台(Vercel、Netlify、Cloudflare Pages 等),在 CI 环境中自动选择合适的 adapter。本地开发默认输出 Node.js 格式。
adapter-vercel
专为 Vercel 优化,支持 Edge Functions、Serverless Functions、ISR 增量静态再生,自动选择最优渲染模式。
adapter-cloudflare
部署到 Cloudflare Pages + Workers,在全球 300+ 节点的边缘网络运行,延迟极低。
adapter-node
生成独立的 Node.js 服务器,可部署到任意支持 Node.js 的环境(VPS、Docker、Railway 等)。
adapter-static
生成纯静态 HTML/CSS/JS 文件,适合完全静态的站点(博客、文档),可部署到 GitHub Pages、Nginx 等。
Vercel 部署
一键部署
# 1. 安装 Vercel adapter(通常 adapter-auto 已包含)
npm install -D @sveltejs/adapter-vercel
# 2. 更新 svelte.config.js
// svelte.config.js
import adapter from '@sveltejs/adapter-vercel';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
export default {
preprocess: vitePreprocess(),
kit: {
adapter: adapter({
// 每个路由的运行时配置
runtime: 'edge', // 'edge' | 'nodejs18.x' | 'nodejs20.x'
regions: ['hkg1'], // 香港节点,对中国用户更快
split: true // 每个路由独立的 Serverless Function
})
}
};
# 3. 安装 Vercel CLI 并部署
npm install -g vercel
vercel login
vercel --prod
# 或者连接 GitHub 仓库,每次 push 自动部署
# 在 vercel.com 中 import 你的仓库
Cloudflare Pages 部署
// svelte.config.js — Cloudflare adapter
import adapter from '@sveltejs/adapter-cloudflare';
export default {
kit: {
adapter: adapter({
routes: {
include: ['/*'],
exclude: ['/static/*']
}
})
}
};
# 使用 Wrangler CLI 部署
npm install -g wrangler
wrangler login
npm run build
wrangler pages deploy .svelte-kit/cloudflare
Node.js 自托管
// svelte.config.js — Node adapter
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
adapter: adapter({
out: 'build', // 输出目录
precompress: true, // 预压缩 Brotli/Gzip
envPrefix: 'APP_' // 环境变量前缀
})
}
};
# 构建
npm run build
# 启动服务器
node build/index.js
# 配置端口和 host
PORT=3000 HOST=0.0.0.0 node build/index.js
Docker 部署
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY build ./build
EXPOSE 3000
ENV PORT=3000
CMD ["node", "build/index.js"]
环境变量
$env 模块
SvelteKit 提供了类型安全的环境变量访问方式,通过 $env 模块自动区分公开变量和私有变量:
// 私有环境变量(只在服务端可用)
// 在 +page.server.ts 或 +server.ts 中使用
import { DATABASE_URL, JWT_SECRET } from '$env/static/private';
import { env } from '$env/dynamic/private'; // 运行时动态读取
// 公开环境变量(客户端可访问,需要 PUBLIC_ 前缀)
import { PUBLIC_API_URL } from '$env/static/public';
import { env as publicEnv } from '$env/dynamic/public';
# .env(开发环境)
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
JWT_SECRET=your-secret-key
# 公开变量(PUBLIC_ 前缀)
PUBLIC_API_URL=https://api.example.com
PUBLIC_ANALYTICS_ID=UA-12345
不要将私密变量暴露给客户端
只有以 PUBLIC_ 前缀命名的变量才能在客户端使用。数据库密码、API 密钥等永远不要使用 PUBLIC_ 前缀或在 +page.ts(通用 load)中使用。
静态生成
// 对单个路由开启预渲染
export const prerender = true;
// 全局预渲染配置(svelte.config.js)
export default {
kit: {
adapter: adapter(),
prerender: {
handleHttpError: 'warn', // 遇到错误时警告而不是失败
crawl: true, // 自动爬取 a[href] 链接
entries: ['/', '/about'] // 手动指定预渲染入口
}
}
};
SvelteKit Adapter 的工作原理
什么是 Adapter?
SvelteKit 的核心是框架无关的——它不假设你的代码运行在 Node.js、Edge Runtime 还是浏览器。Adapter 是部署目标的"翻译器",将 SvelteKit 应用转化为目标平台能够运行的形式:
adapter-node(Node.js 服务器)
生成一个标准的 Node.js HTTP 服务器(Express 兼容)。适合自托管服务器、Docker 容器、VPS 部署。输出文件包含
handler.js(可集成到现有 Express 应用)和独立的 index.js 入口。adapter-vercel(Vercel)
将每个路由转化为 Vercel 的 Serverless Function 或 Edge Function。自动利用 Vercel 的 ISR(增量静态再生成)特性。预渲染的页面部署到 CDN,动态路由部署为函数。
adapter-cloudflare(Cloudflare Pages)
将动态路由转化为 Cloudflare Workers(V8 隔离,不是 Node.js)。在边缘节点运行,全球 200+ 节点,延迟极低。限制:不能使用 Node.js 特定 API(
fs、child_process),需要使用 Web 标准 API。adapter-static(纯静态)
将整个应用预渲染为静态 HTML/CSS/JS 文件,没有服务端代码。适合博客、文档网站、落地页。要求所有路由都能预渲染(不能有用户特定数据)。可以部署到任何静态文件服务器(GitHub Pages、Netlify、Nginx)。
环境变量的安全边界
SvelteKit 环境变量的访问控制:
服务端专用(安全,永不暴露给客户端):
import { DATABASE_URL } from '$env/static/private'
import { env } from '$env/dynamic/private'
只能在 +page.server.ts, +layout.server.ts, +server.ts 中使用
客户端可用(PUBLIC_ 前缀,安全地暴露):
import { PUBLIC_API_URL } from '$env/static/public'
import { env } from '$env/dynamic/public'
可以在所有文件(包括 +page.svelte)中使用
静态 vs 动态:
$env/static/* → 构建时替换(类似 #define),值内联到代码中
$env/dynamic/* → 运行时读取(process.env),支持动态更新
安全保证:
SvelteKit 会在构建时检测非 PUBLIC_ 变量是否被客户端代码引用
如果检测到私密变量被暴露,构建会失败并报错
生产部署检查清单
部署前检查清单:
性能:
□ 图片使用 <enhanced:img> 或外部 CDN(避免大文件内联 base64)
□ 数据库查询有适当的索引
□ 使用 depands() + invalidate() 而非 invalidateAll()(精确失效)
□ {#each} 列表都有 key
安全:
□ 所有敏感变量使用 $env/static/private(非 PUBLIC_)
□ Form Actions 有输入验证(Zod Schema)
□ API 端点有认证检查
□ CSRF 保护未被关闭(默认开启)
□ 数据库查询使用参数化(ORM 默认处理)
SEO(如果需要):
□ 所有页面有 <svelte:head> 中的 title 和 description
□ 动态路由实现了 prerender 或 SSR(非纯 CSR)
□ 添加 sitemap.xml(通过 +server.ts 动态生成)
Docker 容器化部署
# 第一步:安装 adapter-node
npm install -D @sveltejs/adapter-node
# svelte.config.js
# import adapter from '@sveltejs/adapter-node';
# export default { kit: { adapter: adapter() } };
# 构建应用
npm run build
# Dockerfile(多阶段构建)
# 阶段1:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production # 移除 devDependencies
# 阶段2:运行
FROM node:20-alpine AS runner
WORKDIR /app
# 只复制运行所需文件
COPY --from=builder /app/build ./build
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
# adapter-node 的构建产物监听 3000 端口
ENV PORT=3000
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider http://localhost:3000/health || exit 1
CMD ["node", "build"]
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- JWT_SECRET=super-secret-key
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
CI/CD 自动部署(GitHub Actions)
# .github/workflows/deploy.yml
name: Deploy to Vercel
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run check # TypeScript 类型检查
- run: npm run test # 单元测试(vitest)
- run: npm run test:e2e # E2E 测试(playwright)
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
- name: Deploy to Vercel
run: npx vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
性能监控与优化
Web Vitals
Google 定义的核心性能指标:LCP(最大内容绘制,<2.5s)、FID/INP(交互响应延迟,<100ms)、CLS(累积布局偏移,<0.1)。SvelteKit 的 SSR 对这些指标友好,服务端渲染的 HTML 直接显示,无需等待 JS。
Code Splitting
SvelteKit 自动按路由分割代码,每个页面只加载自己需要的 JS。不需要手动 dynamic import(),Vite 自动处理。
Preloading
SvelteKit 自动在用户鼠标悬停到链接时预加载目标页面的 JS 和数据(通过 prefetch),点击时页面即时切换,无等待感。
<!-- src/hooks.server.ts:添加性能监控钩子 -->
export const handle = async ({ event, resolve }) => {
const start = Date.now();
const response = await resolve(event);
const duration = Date.now() - start;
response.headers.set('Server-Timing', `total;dur=${duration}`);
// 慢请求告警
if (duration > 1000) {
console.warn(`Slow request: ${event.url.pathname} took ${duration}ms`);
}
return response;
};
// src/app.html:添加 Web Vitals 监控
// 在 %sveltekit.body% 后添加:
// <script type="module">
// import { onCLS, onINP, onLCP } from 'web-vitals';
// function sendToAnalytics(metric) {
// fetch('/api/vitals', { method: 'POST', body: JSON.stringify(metric) });
// }
// onCLS(sendToAnalytics);
// onINP(sendToAnalytics);
// onLCP(sendToAnalytics);
// </script>
本章小结 · 恭喜完成 Svelte 5 / SvelteKit 课程!
- Adapter 是部署目标的适配器:node(自托管服务器)、vercel(Serverless)、cloudflare(Edge)、static(纯静态),按需选择;adapter-auto 在 CI 中自动检测。
- Docker 容器化:使用多阶段构建(builder + runner),构建阶段生成 build 目录,运行阶段只复制必需文件;通过
npm prune --production减少镜像体积。 - Cloudflare Workers 不是 Node.js:基于 V8 隔离,不支持 fs/child_process 等 Node 特有 API;使用 Web 标准 API(fetch、Request、Response)替代。
- 环境变量安全边界:私密变量用
$env/static/private,客户端变量必须加PUBLIC_前缀;SvelteKit 构建时强制检查,防止敏感信息泄漏。 - prerender = true 将页面静态化,部署到 CDN,速度最快无服务器成本;适合内容稳定的页面(博客、文档、落地页)。
- 性能优化:SvelteKit 自动代码分割和路由预加载;server-timing 头部追踪服务器端性能;Web Vitals 监控用户体验指标。