
svelte-runtime
Svelte 5 运行时技能。当用户需要使用 Stores、Context、生命周期钩子(onMount/onDestroy/tick)、命令式组件 API(mount/unmount/render/hydrate)、Hydratable Data、Best Practices 或 Vitest 测试时使用。
- Installs
- 85
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/full-stack-skills/svelte-skills --skill svelte-runtime- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads svelte-runtime automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Svelte Runtime Reference (Svelte 5)
本技能覆盖 Svelte 5 的运行时 API,包括跨组件状态(Stores/Context)、生命周期、命令式 API、SSR 和测试。
When to use this skill
当用户需要跨组件共享状态、处理组件生命周期、使用 mount/render 等命令式 API、或编写 Vitest 组件测试时使用本技能。
Critical: Stores (svelte/store)
Store 是一种跨组件共享响应式状态的老方式(Svelte 5 推荐用 .svelte.js 中的 $state 对象替代)。
writable
import { writable } from 'svelte/store';
const count = writable(0);
count.subscribe(v => console.log(v)); // 订阅
count.set(1); // 设置值
count.update(n => n + 1); // 更新
readable(不可从外部设置)
import { readable } from 'svelte/store';
const time = readable(new Date(), (set) => {
const interval = setInterval(() => set(new Date()), 1000);
return () => clearInterval(interval);
});
derived
import { derived } from 'svelte/store';
const doubled = derived(count, $c => $c * 2);
const combined = derived([a, b], ([$a, $b]) => $a + $b);
readonly
import { readonly, writable } from 'svelte/store';
const readOnlyStore = readonly(writableStore);
在组件中使用
<script>
import { count } from './store.js';
console.log($count); // $ 前缀订阅
$count = 2; // 自动调用 .set()
</script>
Store 必须在组件顶层声明;不要在变量前加
$前缀(那是$count,不是count)。
Svelte 5 推荐替代方案:
// state.svelte.js
export const userState = $state({ name: '', count: 0 });
// 其他组件直接 import
Critical: Context (svelte)
跨组件层级传递数据,无需 props 层层透传(prop-drilling):
setContext / getContext
// Parent.svelte
<script>
import { setContext } from 'svelte';
setContext('key', 'hello');
</script>
// Child.svelte
<script>
import { getContext } from 'svelte';
const msg = getContext('key');
</script>
createContext(推荐,类型安全)
// context.ts
import { createContext } from 'svelte';
export const [getUserContext, setUserContext] = createContext<User>();
// Parent.svelte
<script> setUserContext({ name: 'Ada' }); </script>
// Child.svelte
<script> const user = getUserContext(); </script>
响应式 Context
将 $state 对象存入 Context:
setContext('counter', counterState);
// ❌ 不要重新赋值整个对象
// counterState = { count: 0 }
// ✅ 直接修改属性
counterState.count = 0;
Critical: Lifecycle Hooks
Mental model: Svelte 5 的生命周期只有两个阶段 —— 创建 与 销毁。中间的"状态更新"由 effect 处理,因为响应式的最小单位是 effect,不是组件。所以没有
beforeUpdate/afterUpdate钩子。
onMount
组件挂载到 DOM 后执行(SSR 时不运行):
<script>
import { onMount } from 'svelte';
onMount(() => {
console.log('mounted');
return () => console.log('unmounted'); // 返回清理函数
});
</script>
返回的函数在组件卸载时调用;如果传入 async 函数则清理函数不会被调用(async 函数总是返回
Promise)。需要异步任务 + 清理时,用 IIFE 包裹,外部箭头函数同步返回清理函数。
onDestroy
组件卸载前执行(SSR 时也运行):
<script>
import { onDestroy } from 'svelte';
onDestroy(() => cleanup());
</script>
tick
等待 DOM 更新完成后再继续:
<script>
import { tick } from 'svelte';
$effect.pre(() => {
// DOM 更新前
tick().then(() => {
// DOM 已更新完成
});
});
</script>
生命周期与 mount/unmount/hydrate 的配合
| 阶段 | mount() | hydrate() | render() (SSR) | unmount() |
|---|---|---|---|---|
| 同步:组件 script、state、模板 | ✓ | ✓ | ✓ | — |
| 同步:插入 DOM / 输出字符串 | ✓ 替换 target | ✓ 复用 SSR DOM | ✓ 返回 head+body | — |
微任务:$effect / onMount 触发 | ✓ | ✓ | ✗ | — |
| 同步:清理 effect + onDestroy | — | — | ✓(render 完成后) | ✓ |
| 异步:过渡 (outro) | — | — | — | outro:true 时等待 |
mount()返回时 effect 和onMount都还没跑;要立刻让它们跑就flushSync()。hydrate()同理。tick()和flushSync()在服务端是 no-op(没有响应式调度)。
Critical: Imperative Component API
mount(客户端挂载)
import { mount } from 'svelte';
import App from './App.svelte';
const app = mount(App, {
target: document.querySelector('#app'),
props: { name: 'world' }
});
unmount(卸载)
import { mount, unmount } from 'svelte';
unmount(app, { outro: true }); // 播放过渡后卸载
render(服务端渲染)
import { render } from 'svelte/server';
const { head, body } = await render(App, { props: { data } });
hydrate(客户端水合)
复用 SSR HTML 并激活为交互式:
import { hydrate } from 'svelte';
const app = hydrate(App, { target: document.querySelector('#app') });
Critical: Hydratable Data
SSR 时序列化数据,客户端水合时复用(避免重复请求):
<script>
import { hydratable } from 'svelte';
const user = await hydratable('user', () => getUser());
</script>
<h1>{user.name}</h1>
CSP 支持
hydratable() 会在 render() 返回的 head 中嵌入一段 inline <script>。CSP 默认会拦截它,需要用 nonce 或 hash 放行:
// 动态 SSR:每请求一个 nonce
const nonce = crypto.randomUUID();
const { head, body } = await render(App, {
csp: { nonce }
});
// 响应头同步加上:
// Content-Security-Policy: script-src 'self' 'nonce-${nonce}'
// 静态 SSG:使用 hash
const { head, body, hashes } = await render(App, {
csp: { hash: true }
});
// Content-Security-Policy: script-src ${hashes.script.map(h => `'${h}'`).join(' ')}
重要:
- 没用
hydratable()时render()不输出 inline<script>,CSP 严格模式不会拦截任何东西。 - inline 事件处理器(
<button onclick={...}>)不是<script>标签,不需要 nonce。 - 推荐 nonce 模式,hash 模式将来会和 streaming SSR 冲突。
- 详见 references/csp-reference.md。
Critical: Best Practices
$state
// ✅ 只对需要响应式的变量用 $state
let count = $state(0);
// ✅ 大数组/不可变数据用 $state.raw
let apiData = $state.raw([]);
apiData = await fetchData(); // 重新赋值触发更新
$derived
// ✅ 派生值用 $derived
let doubled = $derived(count * 2);
// ❌ 不要用 $effect 同步派生
let square;
$effect(() => { square = num * num; }); // ❌
let square = $derived(num * num); // ✅
$effect
// ✅ 仅用于副作用
$effect(() => { myChart.resize(); });
// ❌ 不要同步状态
$effect(() => { left = total - spent; }); // ❌
Props
// ✅ 依赖 props 的值用 $derived
let { type } = $props();
let color = $derived(type === 'danger' ? 'red' : 'green');
事件
<!-- ✅ 现代事件属性 -->
<button onclick={handleClick}>click</button>
<!-- ❌ 旧式 on:click -->
<button on:click={handleClick}>click</button>
<!-- ✅ 监听 window 事件 -->
<svelte:window onkeydown={handleKey} />
Snippets
<!-- ✅ 推荐:使用 snippet -->
{#snippet footer()}
<p>footer</p>
{/snippet}
Each blocks
<!-- ✅ 始终使用 key -->
{#each items as item (item.id)}
<li>{item.name}</li>
{/each}
Context
// ✅ 用 createContext 提供类型安全
import { createContext } from 'svelte';
const [getCtx, setCtx] = createContext<MyCtx>();
Avoid Legacy Features
// ✅ Runes mode 全是新项目的默认
let count = $state(0); // ✅
$: count++; // ❌ legacy
export let name; // ❌
let { name } = $props(); // ✅
on:click={fn} // ❌
onclick={fn} // ✅
<slot /> // ❌
{@render children()} // ✅
<svelte:component this={x} /> // ❌
<svelte:element this={x} /> // ✅
Critical: Testing (Vitest)
安装配置
npm install -D vitest
// vite.config.js
export default defineConfig({
resolve: process.env.VITEST
? { conditions: ['browser'] }
: undefined
});
单元测试
// multiplier.svelte.js
export function multiplier(initial, k) {
let count = $state(initial);
return {
get value() { return count * k; },
set: (c) => { count = c; }
};
}
// test
import { multiplier } from './multiplier.svelte.js';
test('multiplier', () => {
let double = multiplier(0, 2);
expect(double.value).toEqual(0);
double.set(5);
expect(double.value).toEqual(10);
});
组件测试
import { mount, unmount } from 'svelte';
import { expect, test } from 'vitest';
test('MyComponent', () => {
const comp = mount(MyComponent, { target: document.body, props: { name: 'Ada' } });
expect(document.body.innerHTML).toContain('Ada');
unmount(comp);
});
flushSync
强制同步执行所有待处理效果(测试中常用):
import { flushSync } from 'svelte';
flushSync();
Quick Fixes
| 问题 | 解决方案 |
|---|---|
| 状态在组件间不同步 | 用 Context(跨层级)或 .svelte.js(全局) |
| onMount 清理不执行 | 确保传入同步函数(不是 async),需要异步时用 IIFE 包裹 |
| SSR 后组件不交互 | 用 hydrate 而非 mount |
| 测试中状态不更新 | 用 flushSync() 强制同步执行 |
| Context 断开链接 | 不要重新赋值整个 Context 对象 |
| mount 后 effect 没运行 | mount() 同步返回,但 effect 在下一个 microtask 才跑;需要立刻跑就 flushSync() |
| CSP 阻止 hydratable 脚本 | 用 csp: { nonce }(动态)或 csp: { hash: true }(静态),并在响应头里同步声明 |
| 异步 onMount 拿不到清理 | 外部箭头同步 return () => controller.abort(),async 逻辑放 IIFE 里面 |
Gotchas
- Store
$前缀是订阅语法 —$store在模板和 script 中都是订阅,非$前缀的变量是普通值 - Context 链接断开 — 重新赋值整个对象会断开响应式链接,改用
.count = 0而非obj = {count:0} mount不运行$effect— effects 在组件挂载后由 microtask 触发- 测试中
$effect.root— 涉及 effects 的测试需要$effect.root()包裹 render只在 SSR 环境可用 — 客户端用mount- async
onMount的清理会被忽略 — async 函数永远返回 Promise,Svelte 拿不到清理函数;用 IIFE 模式 hydrate()不会同步运行 effect — 跟mount()一样,hydration 后要用flushSync()让 effect 跑起来- CSP nonce 是一次性的 — 每请求一个新 nonce;hash 模式与未来的 streaming SSR 冲突
- hydration 随机值会不匹配 —
Math.random()/Date.now()在 SSR 和 CSR 不同;用hydratable()包裹
FAQ
Q: 什么时候用 Store vs Context vs .svelte.js?
A: Store:跨全应用共享的简单值;Context:组件树局部共享;.svelte.js $state:推荐的新方式,可替代 Store。
Q: tick 和 await Promise.resolve() 有什么区别?
A: tick() 保证在 DOM 更新后解析,Promise.resolve() 不等待 Svelte 的更新周期。
Q: tick() 和 flushSync() 怎么选?
A: await tick() 适合异步用户代码;flushSync() 适合测试和需要立即同步 DOM 的外部库同步场景。
Q: 如何测试带有 $effect 的代码?
A: 用 flushSync() 强制执行,使用 $effect.root() 包裹测试代码。
Q: SSR 后 hydration 报错?
A: 确保 SSR 和 CSR 的 HTML 结构一致;用 hydrate 而非 mount。
Q: 什么时候用 onMount vs $effect?
A: onMount 是"挂载后跑一次"的副作用;$effect 是"依赖变化就重跑"的反应式副作用。
Q: hydrate 的 inline 脚本被 CSP 阻止了怎么办?
A: 用 csp: { nonce } 在 render 时给脚本打上 nonce,并在响应头同步声明;静态站点用 csp: { hash: true } 拿 hashes.script。
Examples
Practical examples demonstrating Svelte 5's runtime APIs.
| File | Description |
|---|---|
| examples/README.md | Entry point with quick reference |
| examples/mount-hydrate.md | 9 examples: mount, unmount, hydrate, render, flushSync, tick |
| examples/ssr-patterns.md | SSR patterns: async render, streaming, hydration, CSP |
| examples/onmount-tick.md | 15 lifecycle examples: onMount (sync/async/cleanup), onDestroy, tick for focus/measure/scroll, $effect.pre pattern |
| examples/csp-examples.md | 8 CSP examples: nonce (Express/SvelteKit/Cloudflare), hash (SSG), diagnostic tips |
References
In-depth technical references for Svelte 5's runtime APIs.
| File | Description |
|---|---|
| references/README.md | Entry point with quick reference |
| references/mount-unmount-reference.md | Deep dive: mount/unmount/hydrate lifecycle, flushSync, tick |
| references/ssr-reference.md | SSR deep dive: render, async SSR, CSP, hydration |
| references/lifecycle-runtime-reference.md | Lifecycle in mount/hydrate runtime: when effects run, onMount timing, tick vs flushSync, SSR phase matrix |
| references/csp-reference.md | CSP nonce vs hash, runtime configuration, streaming compatibility |
FAQ
What does the svelte-runtime skill do?
Svelte 5 运行时技能。当用户需要使用 Stores、Context、生命周期钩子(onMount/onDestroy/tick)、命令式组件 API(mount/unmount/render/hydrate)、Hydratable Data、Best Practices 或 Vitest 测试时使用。
How do I install svelte-runtime?
Run npx skills add https://github.com/full-stack-skills/svelte-skills --skill svelte-runtime in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/svelte-runtime/ (personal) or .claude/skills/svelte-runtime/ (project).
Which AI agents can use svelte-runtime?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is svelte-runtime safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains svelte-runtime?
It is published by full-stack-skills in full-stack-skills/svelte-skills. It has 85 recorded installs.
More from full-stack-skills/svelte-skills
svelte-runes
full-stack-skills/svelte-skills
Svelte 5 Runes 响应式系统技能。当用户需要使用 $state/$derived/$effect/$props/$bindable/$inspect/$host 等符文,或理解 Svelte 5 显式响应式与 Svelte 4 隐式响应式的区别时使用。
svelte-template-syntax
full-stack-skills/svelte-skills
Svelte 5 模板语法技能。当用户需要使用 {if}/{each}/{await}/{snippet} 等块级语法、{@render}/@{html} 等模板标签、bind:、use:/transition:/in:/out:/animate:、style:/class/class:、{@attach} 等指令,或理解属性、事件、文本表达式等基础模板语法时使用。
svelte-legacy-apis
full-stack-skills/svelte-skills
Svelte 5 Legacy API 技能。当用户需要维护或迁移 Svelte 4 代码,理解 Reactive let/$:/export let/Slots/createEventDispatcher/$$props 等已废弃但仍可用的 Legacy API 时使用。
svelte-lifecycle
full-stack-skills/svelte-skills
Svelte 5 生命周期、Stores、Context、Testing 技能。当用户需要在 Svelte 5 中使用 onMount/onDestroy/tick 生命周期钩子、使用 writable/derived stores 管理状态、使用 createContext 共享组件树状态、编写 Vitest/Storybook/Playwright 测试时使用。
svelte-reference
full-stack-skills/svelte-skills
Svelte 5 API 参考技能。当用户需要查阅 svelte/action、svelte/store、svelte/transition、svelte/animate、svelte/easing、svelte/compiler、svelte/events 的具体 API,或需要查看编译器错误/警告代码时使用。
sveltekit-advanced
full-stack-skills/svelte-skills
SvelteKit 高级功能指南 - 状态管理、远程函数(Remote Functions)、环境变量、Hooks、错误处理、链接选项、Service Workers、服务端模块、快照(快照/Shallow Routing)、$app/ 模块、$lib、$service-worker。
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.