用途
该技能用于审查 Svelte 组件是否符合 Svelte 5 的惯用写法,识别从 React、Vue 或 Svelte 4 带入的反模式,并给出 Svelte 5 重构建议。其核心目标是改变开发者的默认思维:在设计组件、放置状态、建模响应式以及审查 UI 代码时,优先选择符合 Svelte 5 心智模型的做法。
典型失败模式是:代码能编译,但思维方式仍停留在 React、Vue 或 Svelte 4——用 effect 代替派生值和事件、把 props 镜像进 state、条件反射式使用全局 store、默认使用双向绑定、使用可点击的 div、在新代码中使用 Svelte 4 的组件 API。
该技能是 Svelte 组件审查的通用入口;涉及 SvelteKit 层面的问题,可配合 sveltekit 技能使用。
主要能力
技能围绕以下原则组织:
让响应式可见
- 响应式是读取追踪的:$derived/$effect 依赖运行时读取的内容,若意外重跑应检查其读取,而非依赖数组。
- 派生状态用 $derived,不用 $effect:纯函数式的状态派生应使用 $derived;effect 用于副作用,而非保持变量同步。
- effect 是逃生舱:使用 $effect 前先检查是否有派生值、事件处理器或 bind: getter/setter 可用;仅用于接触外部世界(订阅、定时器、观察器、命令式 API、日志),并返回清理函数。
- runes 可静态分析:是编译器语法而非运行时 hook;可复用状态应写成 .svelte.ts 类或工厂,而非自定义 hook。
- $state 是深层代理,不是 React state:可直接修改本地数组和对象中变化的部分,无需不可变更新仪式。
把状态放在所有权最清晰的地方
- 状态有所有者:本地交互状态归组件;可复用行为归 .svelte.ts 类;后代共享用 context;store 仅用于 store 契约,而非每个变化的值。
- 不要镜像 props,除非确实需要“草稿”:把 props 复制进 $state 会产生两个真相来源;应从 props 派生,或创建具名的可编辑草稿并支持重置/提交。
- context 共享的是身份,不是 provider 重渲染:把响应式对象/类放入 context 并修改其属性;替换普通值不会像 React Provider 更新那样工作。
- 模块级可变状态在 SSR 应用中可疑:在 SvelteKit 中,导出的可变实例会在请求间泄漏;应使用工厂、context 或请求拥有的数据。
围绕所有权设计组件 API
- props 描述输入,回调描述事件:组件事件即回调 props;新代码避免 createEventDispatcher,除非保留旧公开 API。
- 双向绑定是 API 承诺:$bindable 意味着子组件可修改父组件拥有的状态;用于表单控件和有意为之的受控组件,而非默认选项。
- snippets 是渲染函数,不是改名的 slot:当父组件提供 UI 时使用;为其参数加类型,并按角色命名。
- 包装组件应保留平台行为:包装 button 意味着接受 button 属性并保持 type、disabled、焦点和 ARIA 完整。
让 HTML 和编译器工作
- 原生元素优先于自定义行为:button 已处理键盘、焦点、disabled 和无障碍;可点击 div 是对平台的重建。
- 设计系统字段应保留表单语义:在 shadcn-svelte 或 bits-ui 表单中,使用 Field.* 处理标签、分组、描述和错误,而非原始 div、单独导入 Label 或可点击选项行。
- 组件拥有标记,actions/attachments 拥有 DOM 行为:渲染 UI 用组件;给元素附加可复用命令式行为用 action 或 attachment。
- Svelte 5 语法应保持一致:新代码使用 $props、onclick 风格属性、snippets 和回调 props;旧语法仅用于遗留维护。
- 类型化边界,而非每一处:非平凡组件应有 Props 类型;为 snippets 和回调加类型;包装器使用 svelte/elements;避免边界处宽泛的 any。
使用方式
运行审查
- 先检测版本:读取 package.json 中的 svelte 主版本,检查 svelte.config.*。在 Svelte 5 项目中,标记 Svelte 4 模式(export let、on:event、<slot>、createEventDispatcher);在 Svelte 4 项目中,除非任务是迁移,否则不要推荐 Svelte 5 专属语法。
- 应用上述原则,扫描代码异味索引。在提出重写前,先打开链接的参考文档。
- 仅在有证据或明显规模时判断性能:为已识别的 {#each} 加 key,把重活从标记移入 $derived,避免不必要的双向绑定。大多数代码无需手动优化。
- 组织输出:高影响优先(正确性、响应式、无障碍、SSR 泄漏),然后是建议的重写(最小有用改动),最后是锦上添花项。每个点都要关联行为、可维护性或用户影响,而非每个风格细节。
代码异味索引
技能提供了一份代码异味索引,扫描异味后由对应原则给出修复方向,包括:新代码中的旧 Svelte 语法、effect 赋值派生值、effect 响应控件变化、effect 转换绑定值、effect 神秘重跑、在 helper 或 hook 中调用 rune、本地状态的不可变更新仪式、prop 复制进本地 state、默认全局 store/所有者不清、context 值被替换而非修改、SvelteKit 中导出的可变单例、用 createEventDispatcher 发出事件、习惯性使用 $bindable、slot 形状的 API、可点击 div/span、用原始包装器重建 shadcn-svelte 表单、隐藏原生行为的包装器、拥有标记/状态的 action、未加 key 的动态列表、组件边界处宽泛的 any、对用户内容使用 {@html}、组件行为未测试。
适用场景
- 审查 Svelte 5 组件是否符合惯用模式。
- 识别从 React、Vue 或 Svelte 4 带入的反模式。
- 为现有 Svelte 代码提供 Svelte 5 重构建议。
- 在 Svelte 5 项目中保持语法一致性。
限制
- 该技能是 Svelte 组件审查的通用入口;SvelteKit 层面的关注点(路由、布局、load、表单动作、远程函数、cookies、认证、端点、重定向、服务器错误、应用级 SSR/数据流)需配合 sveltekit 技能。
- 在 Svelte 4 项目中,除非任务是迁移,否则不应推荐 Svelte 5 专属语法。
- 性能判断应基于证据或明显规模,大多数代码无需手动优化。
- 上述原则是强默认值,而非僵化法则;不确定时应选择让所有权、依赖和用户语义更明确的方案。
交叉引用
- sveltekit — 路由、布局、load、表单动作、远程函数、cookies、认证、端点、重定向、服务器错误、应用级 SSR/数据流。