agentsclimarketplace

Svelte best practices

Skill morning-start/agent-skills/lang/svelte/svelte-best-practices

AI 编程助手的专业技能库,涵盖 30+ 技能,按 6 类组织

Install
npx -y skills add morning-start/agent-skills --skill svelte-best-practices

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Svelte 最佳实践技能,掌握测试、TypeScript 集成、迁移指南和常见问题解答,编写高质量 Svelte 应用

SKILL.md

4.7 KB, as published. Nobody here has run it

Svelte Best Practices

任务目标

  • 本 Skill 用于:遵循 Svelte 最佳实践,编写高质量代码
  • 能力包含:测试策略、TypeScript 集成、版本迁移、FAQ
  • 触发条件:需要编写测试、配置 TypeScript 或迁移 Svelte 版本时

操作步骤

$state 最佳实践

<script>
  // 仅对需要响应式的变量使用 $state
  let count = $state(0);

  // 大对象使用 $state.raw 优化性能
  let apiData = $state.raw({});
</script>

$derived 优于 $effect

<script>
  // 推荐:使用派生
  let doubled = $derived(count * 2);

  // 避免:使用效果同步状态
  let doubled;
  $effect(() => {
    doubled = count * 2;
  });
</script>

事件处理

<!-- 推荐:使用事件属性 -->
<button onclick={handleClick}>点击</button>

<!-- 避免:使用旧的 on: 指令 -->
<button on:click={handleClick}>点击</button>

Props 处理

<script>
  // 推荐:基于 props 的派生值
  let { type } = $props();
  let color = $derived(type === 'danger' ? 'red' : 'green');
</script>

<!-- 避免:非响应式赋值 -->
<script>
  let { type } = $props();
  let color = type === 'danger' ? 'red' : 'green';
</script>

调试工具

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

  // 追踪依赖
  $effect(() => {
    $inspect.trace();
    doSomeWork();
  });
</script>

测试配置 (Vitest)

// vite.config.js
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'jsdom'
  },
  resolve: process.env.VITEST ? {
    conditions: ['browser']
  } : undefined
});

组件测试

import { mount, unmount, flushSync } from 'svelte';
import { expect, test } from 'vitest';
import Component from './Component.svelte';

test('Component', () => {
  const target = document.body;
  const component = mount(Component, { target, props: { initial: 0 } });

  expect(document.body.innerHTML).toBe('<button>0</button>');

  document.body.querySelector('button').click();
  flushSync();

  expect(document.body.innerHTML).toBe('<button>1</button>');

  unmount(component);
});

TypeScript 配置

// svelte.config.js
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

export default {
  preprocess: vitePreprocess({ script: true })
};

TypeScript Props

<script lang="ts">
  import type { Snippet } from 'svelte';

  interface Props {
    required: number;
    optional?: boolean;
    children: Snippet;
  }

  let { required, optional = false, children }: Props = $props();
</script>

泛型组件

<script lang="ts" generics="T extends { text: string }">
  interface Props {
    items: T[];
    select(item: T): void;
  }

  let { items, select }: Props = $props();
</script>

Svelte 4 到 Svelte 5 迁移要点

let → $state

<!-- Svelte 4 -->
<script>
  let count = 0;
</script>

<!-- Svelte 5 -->
<script>
  let count = $state(0);
</script>

$: → $derived/$effect

<!-- Svelte 4 -->
<script>
  $: doubled = count * 2;
</script>

<!-- Svelte 5 -->
<script>
  let doubled = $derived(count * 2);
</script>

export let → $props

<!-- Svelte 4 -->
<script>
  export let name;
</script>

<!-- Svelte 5 -->
<script>
  let { name } = $props();
</script>

on:click → onclick

<!-- Svelte 4 -->
<button on:click={handleClick}>点击</button>

<!-- Svelte 5 -->
<button onclick={handleClick}>点击</button>

slot → snippet

<!-- Svelte 4 -->
<slot />

<!-- Svelte 5 -->
<script>
  let { children } = $props();
</script>
{@render children?.()}

createEventDispatcher → callback props

<!-- Svelte 4 -->
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  dispatch('change', value);
</script>

<!-- Svelte 5 -->
<script>
  let { onchange } = $props();
  onchange?.(value);
</script>

资源索引

注意事项

  • 优先使用 runes($state, $derived, $effect)而非旧语法
  • 避免在 $effect 中更新状态
  • 使用 keyed each 块提高列表渲染性能
  • 使用 Context 而非全局模块状态防止 SSR 数据泄露

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.