编译时特性 #
一、编译时框架 #
Svelte 是编译时框架,在构建阶段将组件转换为高效的 JavaScript 代码。
text
┌─────────────────────────────────────────────────────────────┐
│ Svelte 编译流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 源代码 (.svelte) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ <script> │ │
│ │ let count = 0; │ │
│ │ </script> │ │
│ │ <button on:click={() => count++}> │ │
│ │ {count} │ │
│ │ </button> │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ 解析器 (Parser) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 解析 HTML、CSS、JavaScript │ │
│ │ 生成 AST(抽象语法树) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ 编译器 (Compiler) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 分析响应式依赖 │ │
│ │ 生成优化代码 │ │
│ │ 作用域化 CSS │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ 输出代码 (.js) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ function create_fragment(ctx) { │ │
│ │ // 直接操作 DOM 的代码 │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
二、编译优化 #
2.1 无虚拟 DOM #
javascript
// React 方式(运行时)
function Component() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
// Svelte 编译后(简化)
function create_fragment(ctx) {
let button;
let t1;
return {
c() {
button = element("button");
t1 = text(ctx[0]);
},
m(target, anchor) {
insert(target, button, anchor);
append(button, t1);
listen(button, "click", ctx[1]);
},
p(ctx, dirty) {
if (dirty & 1) set_data(t1, ctx[0]);
}
};
}
2.2 静态提升 #
svelte
<script>
let count = 0;
</script>
<div class="static-content">
<p>Static text</p>
</div>
<button onclick={() => count++}>
{count}
</button>
编译后静态内容只创建一次:
javascript
// 静态部分提升到模块作用域
const static_content = document.createElement("div");
static_content.className = "static-content";
// ...
function create_fragment(ctx) {
// 只处理动态部分
let button;
let t1;
// ...
}
2.3 事件委托 #
svelte
<script>
let items = [1, 2, 3, 4, 5];
</script>
<ul>
{#each items as item}
<li onclick={() => console.log(item)}>{item}</li>
{/each}
</ul>
编译器会自动优化事件处理,减少内存占用。
2.4 CSS 作用域 #
svelte
<style>
.button {
background: red;
}
</style>
<button class="button">Click</button>
编译后:
css
.button.svelte-xyz123 {
background: red;
}
html
<button class="button svelte-xyz123">Click</button>
三、响应式编译 #
3.1 依赖追踪 #
svelte
<script>
let a = 1;
let b = 2;
$: sum = a + b;
</script>
<p>{sum}</p>
编译器分析依赖关系:
javascript
// 伪代码
function instance($$self, $$props, $$invalidate) {
let a = 1;
let b = 2;
let sum;
// 依赖追踪:sum 依赖 a 和 b
$$self.$$.update = () => {
if ($$.dirty & /* a, b */ 3) {
$$invalidate(2, sum = a + b);
}
};
return [a, b, sum];
}
3.2 精确更新 #
svelte
<script>
let user = { name: 'Alice', age: 25 };
</script>
<p>{user.name}</p>
<p>{user.age}</p>
当 user.name 变化时,只更新第一个 <p>,不会重新渲染整个组件。
3.3 批量更新 #
svelte
<script>
let a = 1;
let b = 2;
function update() {
a = 3;
b = 4;
}
</script>
<p>{a} + {b} = {a + b}</p>
编译器会批量处理更新,只触发一次 DOM 更新。
四、编译选项 #
4.1 svelte.config.js #
javascript
import adapter from '@sveltejs/adapter-auto';
export default {
compilerOptions: {
// 生成开发模式代码
dev: process.env.NODE_ENV === 'development',
// 启用 CSS 作用域
cssHash: ({ hash, css }) => `s-${hash(css)}`,
// 自定义警告处理
warningFilter: (warning) => {
return !warning.code.includes('a11y');
},
// 启用 runes 模式(Svelte 5)
runes: true
},
kit: {
adapter: adapter()
}
};
4.2 预处理器 #
javascript
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import adapter from '@sveltejs/adapter-auto';
export default {
preprocess: vitePreprocess(),
compilerOptions: {
dev: true
}
};
4.3 TypeScript 支持 #
javascript
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
export default {
preprocess: vitePreprocess({
script: {
define: {
'process.env.NODE_ENV': JSON.stringify('production')
}
}
})
};
五、性能优化 #
5.1 减少响应式依赖 #
svelte
<script>
let items = [];
let filter = '';
// 不推荐:每次都计算
$: filtered = items.filter(i => i.includes(filter));
// 推荐:使用函数
function getFiltered() {
return items.filter(i => i.includes(filter));
}
</script>
{#each getFiltered() as item}
{item}
{/each}
5.2 使用 key 优化列表 #
svelte
<script>
let items = [{ id: 1, name: 'A' }, { id: 2, name: 'B' }];
</script>
<!-- 推荐:使用唯一 key -->
{#each items as item (item.id)}
<div>{item.name}</div>
{/each}
<!-- 不推荐:无 key -->
{#each items as item}
<div>{item.name}</div>
{/each}
5.3 避免不必要的重新渲染 #
svelte
<script>
let data = [];
let selectedId = null;
// 推荐:分离状态
let selectedItem = $derived(data.find(i => i.id === selectedId));
</script>
{#each data as item (item.id)}
<Item {item} selected={item.id === selectedId} />
{/each}
5.4 懒加载组件 #
svelte
<script>
import { onMount } from 'svelte';
let HeavyComponent;
let showHeavy = false;
onMount(async () => {
if (showHeavy) {
const module = await import('./HeavyComponent.svelte');
HeavyComponent = module.default;
}
});
</script>
<button onclick={() => showHeavy = true}>Load Heavy Component</button>
{#if HeavyComponent}
<svelte:component this={HeavyComponent} />
{/if}
六、调试技巧 #
6.1 编译输出查看 #
bash
# 查看编译后的代码
npx svelte compile src/App.svelte --output compiled.js
6.2 响应式调试 #
svelte
<script>
let count = 0;
$: {
console.log('count changed:', count);
console.trace('stack trace');
}
</script>
<button onclick={() => count++}>
{count}
</button>
6.3 开发工具 #
svelte
<svelte:options dev={true} />
<script>
let count = 0;
</script>
<button onclick={() => count++}>{count}</button>
七、编译时 vs 运行时 #
7.1 对比 #
| 特性 | Svelte(编译时) | React(运行时) |
|---|---|---|
| 包体积 | ~2KB | ~42KB |
| 运行时开销 | 无 | 虚拟DOM Diff |
| 首次渲染 | 快 | 中等 |
| 更新性能 | 直接DOM操作 | Diff + Patch |
| 开发体验 | 简洁 | 需要理解Hooks |
7.2 编译时优势 #
text
✅ 优势
├── 极小的运行时代码
├── 无虚拟 DOM 开销
├── 编译时优化
├── 更好的性能
└── 简洁的代码
⚠️ 注意
├── 需要构建步骤
├── 调试时看到编译后代码
└── 某些动态特性受限
八、最佳实践 #
8.1 组件拆分 #
svelte
<!-- 推荐:小组件 -->
<script>
let { title, content } = $props();
</script>
<article>
<h2>{title}</h2>
<p>{content}</p>
</article>
<!-- 不推荐:大组件 -->
<script>
// 大量逻辑
</script>
<div>
<!-- 大量模板 -->
</div>
8.2 响应式设计 #
svelte
<script>
// 推荐:明确依赖
let a = 0;
let b = 0;
let sum = $derived(a + b);
// 不推荐:隐式依赖
let c = 0;
$: {
// 复杂逻辑
}
</script>
8.3 样式优化 #
svelte
<!-- 推荐:作用域样式 -->
<style>
.button {
background: red;
}
</style>
<button class="button">Click</button>
<!-- 避免:全局样式污染 -->
<style>
:global(.button) {
background: red;
}
</style>
九、总结 #
| 特性 | 说明 |
|---|---|
| 编译时优化 | 无运行时开销 |
| 静态提升 | 减少重复创建 |
| 精确更新 | 只更新变化部分 |
| CSS 作用域 | 自动隔离样式 |
| 依赖追踪 | 自动分析响应式 |
编译时特性要点:
- Svelte 在编译时完成大部分工作
- 生成的代码直接操作 DOM
- 静态内容被提升优化
- 响应式依赖在编译时分析
- 合理使用 key 优化列表渲染
- 拆分组件提高编译效率
最后更新:2026-03-28