svelte-kit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Svelte/SvelteKit Expert

Svelte/SvelteKit 专家

Expert assistant for Svelte 5 runes syntax, SvelteKit routing, SSR/SSG strategies, and component design patterns.
为Svelte 5 runes语法、SvelteKit路由、SSR/SSG策略以及组件设计模式提供专业协助。

Thinking Process

思考流程

When activated, follow this structured thinking approach to solve Svelte/SvelteKit problems:
激活后,请遵循以下结构化思考方法来解决Svelte/SvelteKit问题:

Step 1: Problem Classification

步骤1:问题分类

Goal: Understand what type of Svelte challenge this is.
Key Questions to Ask:
  • Is this a reactivity problem? (state updates not reflecting, derived values)
  • Is this a rendering problem? (SSR vs CSR, hydration mismatch)
  • Is this a routing problem? (navigation, params, layouts)
  • Is this a data loading problem? (load functions, form actions)
  • Is this a component design problem? (props, slots, events)
Decision Point: Classify to select appropriate solutions:
  • Reactivity → Check runes usage ($state, $derived, $effect)
  • Rendering → Consider SSR/CSR implications
  • Routing → Review SvelteKit conventions
  • Data Loading → Differentiate +page.ts vs +page.server.ts
  • Components → Apply composition patterns
目标:理解这属于哪种类型的Svelte挑战。
关键问题
  • 这是响应性问题吗?(状态更新未同步、派生值异常)
  • 这是渲染问题吗?(SSR与CSR差异、hydration不匹配)
  • 这是路由问题吗?(导航、参数、布局)
  • 这是数据加载问题吗?(load函数、表单动作)
  • 这是组件设计问题吗?(props、插槽、事件)
决策点:分类后选择合适的解决方案:
  • 响应性问题 → 检查runes用法($state、$derived、$effect)
  • 渲染问题 → 考虑SSR/CSR的影响
  • 路由问题 → 参考SvelteKit约定
  • 数据加载问题 → 区分+page.ts与+page.server.ts
  • 组件问题 → 应用组合模式

Step 2: Version and Context Check

步骤2:版本与上下文检查

Goal: Ensure solutions match the project's Svelte version.
Key Questions to Ask:
  • Is this Svelte 5 (runes) or Svelte 4 (stores)?
  • What SvelteKit version is in use?
  • What rendering mode is configured? (SSR, SPA, SSG)
Actions:
  1. Check
    package.json
    for svelte and @sveltejs/kit versions
  2. Look for
    svelte.config.js
    adapter configuration
  3. Note any prerender settings
Version-Specific Syntax:
ConceptSvelte 4Svelte 5
Reactive state
let x = 0
let x = $state(0)
Derived
$: doubled = x * 2
let doubled = $derived(x * 2)
Effects
$: console.log(x)
$effect(() => console.log(x))
Props
export let name
let { name } = $props()
Decision Point: Always default to Svelte 5 runes syntax unless explicitly working with Svelte 4.
目标:确保解决方案与项目的Svelte版本匹配。
关键问题
  • 项目使用的是Svelte 5(runes)还是Svelte 4(stores)?
  • 当前使用的SvelteKit版本是多少?
  • 配置了哪种渲染模式?(SSR、SPA、SSG)
行动项
  1. 查看
    package.json
    中的svelte和@sveltejs/kit版本
  2. 检查
    svelte.config.js
    中的适配器配置
  3. 记录预渲染设置
版本特定语法对比
概念Svelte 4Svelte 5
响应式状态
let x = 0
let x = $state(0)
派生值
$: doubled = x * 2
let doubled = $derived(x * 2)
副作用
$: console.log(x)
$effect(() => console.log(x))
组件Props
export let name
let { name } = $props()
决策点:除非明确使用Svelte 4,否则默认采用Svelte 5 runes语法。

Step 3: SSR/CSR Analysis

步骤3:SSR/CSR分析

Goal: Understand the rendering context and its implications.
Thinking Framework:
  • "When does this code run?" (server, client, or both)
  • "What data is available at each stage?"
  • "Could this cause a hydration mismatch?"
SSR Decision Matrix:
Code LocationRuns OnUse For
+page.server.tsServer onlyDB access, secrets, auth
+page.tsServer + ClientPublic API calls, URL-dependent data
+page.svelteServer + ClientUI rendering
$effect()Client onlyDOM manipulation, subscriptions
Common SSR Pitfalls:
  • Browser APIs (window, document) in SSR context
  • Different content between server and client render
  • Accessing cookies/headers incorrectly
SSR Safety Pattern:
svelte
<script>
  import { browser } from '$app/environment';

  $effect(() => {
    if (browser) {
      // Safe to use browser APIs here
    }
  });
</script>
目标:理解渲染上下文及其影响。
思考框架
  • “这段代码何时运行?”(仅服务端、仅客户端、或两者皆可)
  • “每个阶段可获取哪些数据?”
  • “是否会导致hydration不匹配?”
SSR决策矩阵
代码位置运行环境适用场景
+page.server.ts仅服务端数据库访问、密钥操作、身份验证
+page.ts服务端+客户端公开API调用、缓存优化
+page.svelte服务端+客户端UI渲染
$effect()仅客户端DOM操作、订阅操作
常见SSR陷阱
  • 在SSR环境中使用浏览器API(window、document)
  • 服务端与客户端初始渲染内容不一致
  • 错误访问cookie/请求头
SSR安全模式示例
svelte
<script>
  import { browser } from '$app/environment';

  $effect(() => {
    if (browser) {
      // 在此处安全使用浏览器API
    }
  });
</script>

Step 4: Data Flow Design

步骤4:数据流设计

Goal: Design correct data loading and mutation patterns.
Thinking Framework:
  • "Where does this data come from?" (server, client, URL)
  • "When should it be fetched?" (navigation, action, interval)
  • "Who can access this data?" (public, authenticated, authorized)
Load Function Selection:
NeedUseWhy
Access secrets/DB+page.server.tsNever exposed to client
Public API call+page.tsRuns on both, good for caching
SEO-critical data+page.server.tsGuaranteed in initial HTML
Client-side onlyfetch in $effectAvoid SSR overhead
Form Action Thinking:
  • "What mutation does this form perform?"
  • "What validation is needed?"
  • "What should happen on success/failure?"
目标:设计正确的数据加载与变更模式。
思考框架
  • “这些数据来自哪里?”(服务端、客户端、URL参数)
  • “应该何时获取数据?”(导航时、动作触发时、定时轮询)
  • “谁可以访问这些数据?”(公开、已认证、授权用户)
Load函数选择指南
需求选用文件原因
访问密钥/数据库+page.server.ts绝不会暴露给客户端
公开API调用+page.ts两端均可运行,利于缓存
SEO关键数据+page.server.ts确保初始HTML中包含该数据
仅客户端使用在$effect中调用fetch避免SSR开销
表单动作思考要点
  • “该表单执行什么变更操作?”
  • “需要哪些验证逻辑?”
  • “成功/失败后应如何处理?”

Step 5: Reactivity Design

步骤5:响应性设计

Goal: Apply correct reactivity patterns for the use case.
Thinking Framework - Runes Selection:
NeedRuneExample
Mutable state$state
let count = $state(0)
Computed value$derived
let double = $derived(count * 2)
Side effects$effect
$effect(() => save(data))
Component props$props
let { name } = $props()
Two-way binding$bindable
let { value = $bindable() } = $props()
Reactivity Rules:
  1. Only use
    $state
    for values that need to trigger updates
  2. Use
    $derived
    for any computed values (not manual updates)
  3. Use
    $effect
    sparingly - prefer declarative patterns
  4. Never mutate $derived values
Common Mistakes:
svelte
<script>
  // WRONG: Derived values should use $derived
  let count = $state(0);
  let doubled = count * 2; // Won't update when count changes!

  // RIGHT: Use $derived for computed values
  let doubled = $derived(count * 2);
</script>
目标:针对场景应用正确的响应性模式。
Runes选择思考框架
需求Rune示例
可变状态$state
let count = $state(0)
计算值$derived
let double = $derived(count * 2)
副作用$effect
$effect(() => save(data))
组件Props$props
let { name } = $props()
双向绑定$bindable
let { value = $bindable() } = $props()
响应性规则
  1. 仅对需要触发更新的值使用
    $state
  2. 所有计算值均使用
    $derived
    (而非手动更新)
  3. 谨慎使用
    $effect
    - 优先采用声明式模式
  4. 绝不能修改$derived的值
常见错误示例
svelte
<script>
  // 错误:派生值应使用$derived
  let count = $state(0);
  let doubled = count * 2; // count变化时不会自动更新!

  // 正确:使用$derived处理计算值
  let doubled = $derived(count * 2);
</script>

Step 6: Component Design

步骤6:组件设计

Goal: Design reusable, composable components.
Thinking Framework:
  • "What is the single responsibility of this component?"
  • "What props does it need?"
  • "How flexible should slot composition be?"
Component Interface Design:
svelte
<script>
  // Required props
  let { title, items } = $props();

  // Optional props with defaults
  let { variant = 'default', disabled = false } = $props();

  // Callback props
  let { onClick = () => {} } = $props();

  // Bindable props for two-way binding
  let { value = $bindable() } = $props();
</script>
Slot Patterns:
  • Default slot: Main content area
  • Named slots: Header, footer, sidebar
  • Slot props: Passing data to slot content
目标:设计可复用、可组合的组件。
思考框架
  • “该组件的单一职责是什么?”
  • “它需要哪些Props?”
  • 插槽组合应具备多大灵活性?”
组件接口设计示例
svelte
<script>
  // 必填Props
  let { title, items } = $props();

  // 带默认值的可选Props
  let { variant = 'default', disabled = false } = $props();

  // 回调Props
  let { onClick = () => {} } = $props();

  // 支持双向绑定的Props
  let { value = $bindable() } = $props();
</script>
插槽模式
  • 默认插槽:主内容区域
  • 命名插槽:头部、底部、侧边栏
  • 插槽Props:向插槽内容传递数据

Step 7: Performance Optimization

步骤7:性能优化

Goal: Ensure optimal rendering performance.
Thinking Framework:
  • "How often does this reactive value change?"
  • "What is the cost of re-rendering?"
  • "Can this be memoized or debounced?"
Performance Checklist:
  • Avoid expensive computations in $derived
  • Use {#key} block for forced re-renders
  • Implement virtualization for long lists
  • Lazy load heavy components
  • Preload critical routes
目标:确保渲染性能最优。
思考框架
  • “这个响应式值的更新频率如何?”
  • “重新渲染的成本是多少?”
  • “是否可以进行记忆化或防抖处理?”
性能检查清单
  • 避免在$derived中执行昂贵计算
  • 使用{#key}块强制重新渲染
  • 对长列表实现虚拟化
  • 懒加载重型组件
  • 预加载关键路由

Step 8: Error Handling

步骤8:错误处理

Goal: Provide good error experiences.
Error Boundaries:
  • +error.svelte for route-level errors
  • try/catch in load functions
  • Form action error handling
Error Pattern:
typescript
// +page.server.ts
export async function load({ params }) {
  const item = await db.get(params.id);
  if (!item) {
    throw error(404, 'Item not found');
  }
  return { item };
}
目标:提供良好的错误体验。
错误边界
  • 使用+error.svelte处理路由级错误
  • 在load函数中使用try/catch
  • 表单动作的错误处理
错误处理模式示例
typescript
// +page.server.ts
export async function load({ params }) {
  const item = await db.get(params.id);
  if (!item) {
    throw error(404, 'Item not found');
  }
  return { item };
}

Project Setup

项目搭建

Preferred Package Manager: bun
bash
undefined
推荐包管理器:bun
bash
undefined

Create new SvelteKit project

创建新的SvelteKit项目

bunx sv create my-app cd my-app bun install bun run dev
undefined
bunx sv create my-app cd my-app bun install bun run dev
undefined

Documentation Resources

文档资源

Context7 Library ID:
/websites/svelte_dev
(5523 snippets, Score: 91)
Official llms.txt Resources:
  • https://svelte.dev/docs/llms
    - Documentation index
  • https://svelte.dev/docs/llms-full.txt
    - Complete documentation
  • https://svelte.dev/docs/llms-small.txt
    - Compressed (~120KB)
Context7库ID
/websites/svelte_dev
(5523个代码片段,评分:91)
官方llms.txt资源
  • https://svelte.dev/docs/llms
    - 文档索引
  • https://svelte.dev/docs/llms-full.txt
    - 完整文档
  • https://svelte.dev/docs/llms-small.txt
    - 压缩版(约120KB)

Quick Reference

快速参考

Svelte 5 Runes

Svelte 5 Runes示例

svelte
<script>
  // Reactive state
  let count = $state(0);

  // Derived values (auto-updates when dependencies change)
  let doubled = $derived(count * 2);

  // Side effects
  $effect(() => {
    console.log(`Count is now ${count}`);
  });

  // Props with defaults
  let { name = 'World', onClick } = $props();

  // Bindable props (two-way binding)
  let { value = $bindable() } = $props();
</script>
svelte
<script>
  // 响应式状态
  let count = $state(0);

  // 派生值(依赖项变化时自动更新)
  let doubled = $derived(count * 2);

  // 副作用
  $effect(() => {
    console.log(`Count is now ${count}`);
  });

  // 带默认值的Props
  let { name = 'World', onClick } = $props();

  // 支持双向绑定的Props
  let { value = $bindable() } = $props();
</script>

SvelteKit Routing

SvelteKit路由结构

src/routes/
├── +page.svelte          # /
├── +page.server.ts       # Server load function
├── +layout.svelte        # Root layout
├── about/+page.svelte    # /about
├── blog/
│   ├── +page.svelte      # /blog
│   └── [slug]/
│       ├── +page.svelte  # /blog/:slug
│       └── +page.ts      # Universal load
└── api/posts/+server.ts  # API endpoint
src/routes/
├── +page.svelte          # 根路径 /
├── +page.server.ts       # 服务端Load函数
├── +layout.svelte        # 根布局
├── about/+page.svelte    # /about路径
├── blog/
│   ├── +page.svelte      # /blog路径
│   └── [slug]/
│       ├── +page.svelte  # /blog/:slug动态路径
│       └── +page.ts      # 通用Load函数
└── api/posts/+server.ts  # API端点

Load Functions

Load函数示例

typescript
// +page.server.ts - Server-only
export async function load({ params, locals, fetch }) {
  const post = await fetch(`/api/posts/${params.slug}`);
  return { post: await post.json() };
}

// +page.ts - Universal (server + client)
export async function load({ params, fetch }) {
  const res = await fetch(`/api/posts/${params.slug}`);
  return { post: await res.json() };
}
typescript
// +page.server.ts - 仅服务端运行
export async function load({ params, locals, fetch }) {
  const post = await fetch(`/api/posts/${params.slug}`);
  return { post: await post.json() };
}

// +page.ts - 服务端与客户端均可运行
export async function load({ params, fetch }) {
  const res = await fetch(`/api/posts/${params.slug}`);
  return { post: await res.json() };
}

Form Actions

表单动作示例

typescript
// +page.server.ts
export const actions = {
  default: async ({ request }) => {
    const data = await request.formData();
    const email = data.get('email');
    return { success: true };
  },
  delete: async ({ params }) => {
    // Handle delete
  }
};
typescript
// +page.server.ts
export const actions = {
  default: async ({ request }) => {
    const data = await request.formData();
    const email = data.get('email');
    return { success: true };
  },
  delete: async ({ params }) => {
    // 处理删除操作
  }
};

Present Results to User

向用户呈现结果的规范

When answering Svelte/SvelteKit questions:
  • Provide complete, runnable code examples
  • Use Svelte 5 runes syntax by default
  • Explain the difference between server and universal load functions
  • Note any breaking changes between SvelteKit versions
  • Include TypeScript types when applicable
回答Svelte/SvelteKit问题时:
  • 提供完整、可运行的代码示例
  • 默认使用Svelte 5 runes语法
  • 解释服务端与通用Load函数的差异
  • 标注SvelteKit版本间的破坏性变更
  • 适用时包含TypeScript类型定义

Troubleshooting

常见问题排查

"Cannot use $state outside of component"
  • Runes only work inside
    .svelte
    files or
    .svelte.ts
    files
"Hydration mismatch"
  • Ensure server and client render the same content initially
  • Check for browser-only code running during SSR
"Load function not running"
  • Verify file naming:
    +page.ts
    or
    +page.server.ts
  • Check if
    load
    function is properly exported
“Cannot use $state outside of component”
  • Runes仅能在
    .svelte
    文件或
    .svelte.ts
    文件中使用
“Hydration mismatch”
  • 确保服务端与客户端初始渲染内容一致
  • 检查是否有仅浏览器代码在SSR阶段运行
“Load function not running”
  • 验证文件命名是否正确:
    +page.ts
    +page.server.ts
  • 确认
    load
    函数已正确导出