什么是编译时框架?
传统运行时框架的工作方式
React 和 Vue 是运行时框架:你的应用代码和框架代码一起打包,在浏览器中运行。React 需要在内存中维护一棵虚拟 DOM 树(Virtual DOM),每次状态变化时,React 会重新渲染出一棵新的虚拟 DOM 树,与旧树对比(Diffing),找出差异,再将差异应用到真实 DOM 上——这个过程叫做Reconciliation(调和)。
这种设计的优点是灵活,但缺点也很明显:浏览器必须加载整个框架运行时(React 约 45KB gzip),而且每次更新都要执行 diffing 算法,在复杂应用中产生不必要的计算开销。
Svelte 的编译时思路
Svelte 的作者 Rich Harris 提出了一个不同的问题:"如果我们把这些工作放到构建时来做,而不是放到运行时,会怎样?"
Svelte 是一个编译器——你写的 .svelte 组件文件,经过 Svelte 编译器处理后,会变成精简的、命令式的 JavaScript 代码,这些代码直接精确地操作 DOM,不需要任何框架运行时在场。浏览器加载的只是你自己的业务代码,没有额外的框架 overhead。
一个简单的 Svelte 计数器组件,编译后大约只有 500 字节的 JavaScript,而相同功能的 React 应用需要下载约 45KB 的 React 运行时 + 你的代码。
React / Vue / Svelte 核心差异对比
| 维度 | React | Vue 3 | Svelte 5 |
|---|---|---|---|
| 框架性质 | 运行时库 | 运行时框架 | 编译器 |
| 虚拟 DOM | 有(VDOM) | 有(VDOM) | 无 |
| 运行时体积 | ~45KB gzip | ~22KB gzip | ~2KB gzip |
| 响应式方式 | useState/hooks | ref/reactive | Runes ($state 等) |
| 模板语言 | JSX | 模板+Composition API | .svelte 单文件组件 |
| CSS 作用域 | CSS Modules/styled | scoped attribute | 编译期自动作用域 |
| 全栈框架 | Next.js | Nuxt | SvelteKit |
Svelte 的发展历程
认识 Runes 系统
旧版响应式的局限性
在 Svelte 3/4 中,响应式是通过魔法赋值实现的:只要在 <script> 标签中声明的变量被重新赋值,Svelte 就会自动更新对应的 DOM。这听起来很方便,但有严重的局限:
- 响应式只在组件内部工作,无法将响应式逻辑提取到普通 JS 模块中
- 对象和数组的深层变更不能被自动检测(需要手动触发重赋值)
- 调试困难:不清楚哪些变量是响应式的,哪些不是
$:标签语法看起来像 label 语句,语义不直观
Runes:显式的响应式原语
Runes(符文)是 Svelte 5 引入的一套以 $ 前缀开头的特殊函数,用于显式声明响应式状态。它们不是普通的 JavaScript 函数,而是 Svelte 编译器能识别的特殊语法,会在编译期被转换为高效的响应式代码。
<!-- Svelte 5 Runes 示例 -->
<script>
// $state() 声明响应式变量
let count = $state(0);
// $derived() 声明派生值
let doubled = $derived(count * 2);
// $effect() 声明副作用
$effect(() => {
console.log(`count changed to ${count}`);
});
function increment() {
count++;
}
</script>
<button onclick={increment}>
Count: {count} (doubled: {doubled})
</button>
安装 SvelteKit 项目
前置要求
你需要安装 Node.js 18+(推荐 LTS 版本)和 npm / pnpm / bun 包管理器。验证安装:
node --version # v20.x.x 或更高
npm --version # 10.x.x 或更高
创建项目
# 使用官方脚手架创建 SvelteKit 项目
npx sv create my-app
# 交互式选择:
# Template: SvelteKit minimal / SvelteKit demo app
# TypeScript: Yes (strongly recommended)
# Add-ons: ESLint, Prettier, Vitest
# 进入目录并安装依赖
cd my-app
npm install
# 启动开发服务器
npm run dev
# 打开 http://localhost:5173
SvelteKit 项目目录结构
.svelte 文件的三个部分
每个 .svelte 文件都是一个自包含的组件,由三个可选部分组成:
<!-- src/routes/+page.svelte -->
<!-- 1. Script 块:组件逻辑 -->
<script lang="ts">
// TypeScript / JavaScript 代码
// 组件状态、函数、导入
import { page } from '$app/stores';
let title = $state('Hello Svelte!');
</script>
<!-- 2. Template 块:HTML 模板(无需特定标签包裹) -->
<h1>{title}</h1>
<p>当前路径:{$page.url.pathname}</p>
<!-- 3. Style 块:组件作用域样式 -->
<style>
/* 这里的样式只作用于当前组件 */
h1 {
color: #FF3E00;
font-size: 2rem;
}
</style>
在 script 标签添加 lang="ts" 启用 TypeScript。SvelteKit 内置完整的 TypeScript 支持,包括路由参数类型、load 函数返回值类型等,能显著提升开发体验和代码健壮性。
第一个完整示例:计数器应用
创建计数器组件
<!-- src/lib/components/Counter.svelte -->
<script lang="ts">
// 使用 $props() 声明接收的 props
let { initialValue = 0, label = 'Count' } = $props<{
initialValue?: number;
label?: string;
}>();
// 使用 $state() 声明响应式状态
let count = $state(initialValue);
// 使用 $derived() 派生值
let isEven = $derived(count % 2 === 0);
let status = $derived(isEven ? '偶数' : '奇数');
// 使用 $effect() 追踪副作用
$effect(() => {
document.title = `${label}: ${count}`;
});
function increment() { count++; }
function decrement() { count--; }
function reset() { count = initialValue; }
</script>
<div class="counter">
<h2>{label}</h2>
<div class="display">
<button onclick={decrement}>-</button>
<span class:even={isEven}>{count}</span>
<button onclick={increment}>+</button>
</div>
<p>状态:{status}</p>
<button onclick={reset}>重置</button>
</div>
<style>
.counter {
padding: 1.5rem;
border: 1px solid #ff3e00;
border-radius: 8px;
text-align: center;
}
.display {
display: flex;
align-items: center;
gap: 1rem;
justify-content: center;
margin: 1rem 0;
}
span { font-size: 2rem; font-weight: bold; }
/* :global() 用于选择子组件元素 */
span.even { color: #4ade80; }
</style>
在页面中使用组件
<!-- src/routes/+page.svelte -->
<script lang="ts">
import Counter from '$lib/components/Counter.svelte';
</script>
<main>
<h1>Svelte 5 计数器演示</h1>
<Counter initialValue={10} label="购物车数量" />
<Counter label="浏览次数" />
</main>
Svelte 5 提供了旧版 API 的兼容层,现有的 Svelte 4 代码可以在 Svelte 5 中运行。但新项目强烈推荐直接使用 Runes。混用旧版 $: 语法和 Runes 时,Svelte 会提示警告。
开发工具推荐
# 查看项目依赖和可用脚本
cat package.json
# 常用命令
npm run dev # 启动开发服务器(端口 5173)
npm run build # 生产构建
npm run preview # 预览生产构建结果
npm run check # TypeScript 类型检查
npm run lint # ESLint 代码检查
npm run format # Prettier 格式化
访问 svelte.dev/playground 可以在浏览器中直接试验 Svelte 5 代码,无需本地安装,非常适合快速验证想法。