mcpField
S
svelte-legacy-apis

svelte-legacy-apis

github.com/full-stack-skills開発4117 回インストール5 週間前に更新
リポジトリ

svelte-legacy-apis について

Svelte 4のLegacyコンポーネントを保守し、Svelte 5へ移行する開発者向けのリファレンススキルです。リアクティビティやコンポーネントAPIに加え、Svelte 3から4への移行事項も扱います。

主な機能

  1. 01Legacyのリアクティビティと代入規則の解説
  2. 02props、イベント、slotのリファレンス
  3. 03Legacy APIとRunesの対応表
  4. 04Svelte 3から4への移行情報
  5. 05例、チェックリスト、トラブルシューティング

活用シーン

  1. 01`$:`やトップレベルの`let`を使うコンポーネントの保守
  2. 02`export let`から`$props()`への置き換え
  3. 03配列変更後に更新されない問題の調査
  4. 04Svelte 3から4へのアップグレード時の変更点確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/full-stack-skills/svelte-skills --skill svelte-legacy-apis

インストール後、Claude Code で/svelte-legacy-apisを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
examples/
legacy-mode.md
migration-scripts.md
migration-v4.md
README.md
store-comparison.md
references/
legacy-mode-reference.md
migration-reference.md
migration-v4-reference.md
README.md
store-reference.md

詳細

Svelte Legacy API リファレンス(Svelte 4 → Svelte 5)

このスキルでは、Svelte 4 の Legacy API を扱います。これらの API は Svelte 5 でも Legacy Mode で引き続き利用できますが、Runes への移行が推奨されています。このスキルは Legacy コードの理解と移行のみを目的としており、新しいコードでは Runes を使用してください。

このスキルを使用する場面

ユーザーが Svelte 4 プロジェクトの保守、$: リアクティブステートメントや export let props、createEventDispatcher、Slots の理解、または Legacy コードから Svelte 5 Runes Mode への移行を必要としている場合に、このスキルを使用してください。

重要:リアクティブな let 宣言

Legacy Mode(Runes を使用していないコンポーネント)では、トップレベルの let 宣言は自動的にリアクティブになります:

<script>
  let count = 0; // 自动响应式
</script>

<button on:click={() => count++}>
  {count}
</button>

Svelte 5 の Runes Mode:let count = $state(0)。

配列/オブジェクトの変更に関する注意

Legacy のリアクティビティは代入に基づいています。配列メソッド(.push()、.splice())では更新がトリガーされません:

<script>
  let items = [1, 2, 3];

  function addItem() {
    items.push(4);    // ❌ 不触发更新
    items = items;    // ✅ 触发
    // 或
    items = [...items, 4]; // ✅ 触发
  }
</script>

重要:リアクティブな $: ステートメント

Legacy Mode では、$: ラベル付きステートメントによってリアクティブステートメントを作成します:

<script>
  let a = 1;
  let b = 2;

  $: sum = a + b;              // 依赖 a, b
  $: console.log(`sum = ${sum}`); // 依赖 sum
</script>
トポロジカルソート

$: ステートメントは依存関係に基づいてトポロジカルソートされます(順序は関係ありません):

$: z = y;    // z 依赖 y
$: y = x;    // y 依赖 x
$: x = 5;    // x 无依赖
ブロックステートメント
$: {
  total = 0;
  for (const item of items) total += item.value;
}

重要:export let

Legacy Mode では、export let を使って props を宣言します:

<script>
  export let name;              // 必需 prop
  export let age = 18;          // 带默认值
  export let items = [];         // 数组默认值
</script>

Svelte 5 Runes:let { name, age = 18 } = $props()

再エクスポート(API)
<script>
  export function greet(name) {
    alert(`Hello ${name}!`);
  }
  export const VERSION = '1.0';
</script>

親コンポーネントから bind:this を通じて呼び出します:

<script>
  let greeter;
</script>
<Greeter bind:this={greeter} />
<button on:click={() => greeter.greet('world')}>greet</button>
prop の名前変更
<script>
  export { foo as bar }; // 对外叫 bar,内部叫 foo
</script>

重要:$$props / $$restProps

$$props(渡されたすべての props を取得)
<script>
  let { foo, ...rest } = $$props;
  // foo 是显式 prop,rest 是其余所有 props
</script>

Svelte 5 Runes:let { foo, ...rest } = $props()

$$restProps(残りの props のみ)
<script>
  export let required;
  let { ...rest } = $$props;
</script>

重要:createEventDispatcher

Legacy のイベントディスパッチの仕組み(Svelte 5 では callback props に置き換えられています):

<script>
  import { createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();

  function handleClick() {
    dispatch('change', { value: 42 });
    dispatch('complete'); // 无数据
  }
</script>

<button on:click={handleClick}>发送</button>
イベントの使用
<Component on:change={(e) => console.log(e.detail)} />
型付け(TypeScript)
<script lang="ts">
  const dispatch = createEventDispatcher<{
    change: { value: number };
    complete: null;
  }>();
</script>

Svelte 5 での推奨方法:callback props を直接使用します: <Component onChange={(detail) => handle(detail)} />

重要:Slots

<slot> は Legacy のコンテンツ受け渡しの仕組みです(Svelte 5 では Snippets に置き換えられています):

デフォルト slot

<div class="card">
  <slot />
</div>


<Component>
  <p>内容</p>
</Component>
名前付き slot

<slot name="footer" />
<slot name="header" />


<Component>
  <p slot="header">头部</p>
  <p slot="footer">尾部</p>
</Component>
Slot props(slot にデータを渡す)

<slot value={count} onClick={handleClick} />


<Component let:value let:onClick>
  <p>{value}</p>
  <button on:click={onClick}>click</button>
</Component>

注意:Svelte 5 では、default slot props には let: プレフィックスが必要です。named slots では slot props を公開できません。

$$slots(slot の有無を確認)
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  $: if (!$$slots.footer) {
    // footer slot 未被提供
  }
</script>

重要:svelte:component / svelte:self

<svelte:component>(動的コンポーネント)
<script>
  let Current = FirstComponent;
  $: Current = showSecond ? SecondComponent : FirstComponent;
</script>

<svelte:component this={Current} />

Svelte 5 での推奨方法:<svelte:element this={Current} />

<svelte:self>(再帰コンポーネント)
<script>
  import { svelte:self } from 'svelte';
</script>

<svelte:self />

重要:svelte:fragment


<slot name="title" />
<div>
  <slot name="body" />
</div>


<Component>
  <h1 slot="title">Title</h1>
  <svelte:fragment slot="body">
    <p>多元素</p>
    <p>不会被包裹</p>
  </svelte:fragment>
</Component>

重要:v5 移行のクイックリファレンス

Legacy(Svelte 4)モダン(Svelte 5)
let count = 0(トップレベルでリアクティブ)let count = $state(0)
$: x = exprlet x = $derived(expr)
$: { if (cond) x = v }$effect(() => { if (cond) x = v })
export let proplet { prop } = $props()
$$propslet { ...rest } = $props()
<slot />{@render children()}
createEventDispatchercallback props
on:click={fn}onclick={fn}
<svelte:component this={x}><svelte:element this={x}>
<svelte:self>import Self from './This.svelte' + <Self>
class:cool={isCool}class={{ cool: isCool }}
let:slotProp={value}Snippets による自動受け渡し

注意点

  1. Legacy の $: は代入に基づきます — 配列の .push() などのメソッドでは更新がトリガーされません
  2. Slot props の動作は異なります — default slot では slot props にアクセスできますが、named slots ではできません
  3. createEventDispatcher は非推奨です — Svelte 5 では推奨されていません。新しいコードでは callback props を使用してください
  4. $$slots はコンパイル時に注入されます — script 内で直接使用でき、$: 内からも参照できます
  5. <svelte:self> はインポートが必要です — import { svelte:self } from 'svelte'

重要:Svelte 4 への移行(Svelte 3 → Svelte 4)

Svelte 3 プロジェクトを保守していて Svelte 4 にアップグレードする場合は、以下の破壊的変更を一つずつ確認する必要があります。詳しい比較と自動化スクリプトについては、examples/migration-v4.md と references/migration-v4-reference.md を参照してください。ソースの基準は /tmp/svelte-llms.txt:6182 です。

推奨される開始方法:npx svelte-migrate@latest svelte-4 —— このスクリプトで大半の項目を自動処理できます。それ以外は手動で対応する必要があります。

最低バージョン要件
{
  "engines": { "node": ">=16" },
  "devDependencies": {
    "svelte": "^4.0.0",
    "@sveltejs/kit": ">=1.20.4",
    "vite-plugin-svelte": ">=2.4.1",
    "svelte-loader": ">=3.1.8",
    "rollup-plugin-svelte": ">=7.1.5",
    "typescript": ">=5"
  }
}
主要破坏性变更速查
类别Svelte 3Svelte 4
Bundler browser condition可选Rollup browser: true / Webpack conditionNames: ['browser']
CJS 输出支持移除(编译器、svelte/register、runtime)
createEventDispatcher 类型可选 payload严格:T | undefined 可选;T 必填;null 禁 detail
Action / ActionReturnparams 隐式 any必须显式 Action<HTMLElement, T>
onMount 异步清理不报错返回 Promise 的清理函数会被忽略(TS 报错)
Custom Element<svelte:options tag="x" /><svelte:options customElement="x" />(字符串或对象)
SvelteComponentTyped与 SvelteComponent 并存弃用,统一为 SvelteComponent
Transitions 默认范围任意祖先块触发仅直接父块触发,加 |global 恢复旧行为
Default slot bindingsnamed slot 也可见仅 default slot 可见
Preprocessor 顺序markup×N, script×N, style×Nmarkup, script, style ×N(每个 preprocessor 内部三段)
eslint-plugin-svelte3推荐弃用,改 eslint-plugin-svelte
inert on outroing不应用默认应用(无障碍改进)
classList.toggle兼容老浏览器需要 polyfill
CustomEvent兼容老浏览器需要 polyfill
derived falsy 值警告抛错
svelte/internal 类型暴露已移除
svelte.JSX 命名空间用改 svelteHTML / svelte/elements
库作者 peerDependencies^3^3 || ^4
自动化脚本能处理的
  • tag= → customElement=(字符串形式)
  • SvelteComponentTyped → SvelteComponent
  • Action / ActionReturn 泛型参数
  • Transitions 默认行为(添加 |global 修饰符)
需要手动处理的
  • Bundler browser condition 配置(Rollup / Webpack)
  • 严格类型错误的修复(createEventDispatcher payload)
  • onMount 异步清理改同步
  • Preprocessor name 属性 + 顺序调整
  • ESLint 插件替换 + 配置迁移
  • derived falsy 值边界条件
Custom Element 升级
<svelte:options tag="my-counter" />
<svelte:options customElement={{ tag: 'my-counter', props: { initial: { type: Number } } }} />
onMount 异步清理反模式
// ❌ v4 报错且永远不清理
onMount(async () => { const data = await fetch('/api'); setup(data); return () => teardown(); });
// ✅ 同步返回值
onMount(() => { fetch('/api').then(setup); return () => teardown(); });
Preprocessor 顺序:MDsveX 必须最前
// svelte.config.js
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import { mdsvex } from 'mdsvex';

export default {
  preprocess: [
    mdsvex({ name: 'mdsvex' }),         // 先 markup 再 script
    vitePreprocess({ name: 'vite' })
  ]
};

v3:所有 markup → 所有 script → 所有 style。v4:每个 preprocessor 内部 markup → script → style,再下一个。每个 preprocessor 必须声明 name。

库作者的 peerDependencies
{
  "peerDependencies": { "svelte": "^3.0.0 || ^4.0.0" },
  "devDependencies": { "svelte": "^4.0.0" }
}
Run-it-Yourself Checklist
npm install svelte@^4                    # 1. 升级依赖
npx svelte-migrate@latest svelte-4       # 2. 跑迁移脚本
npx svelte-check                          # 3. 看 TypeScript
npm test                                   # 4. 跑测试

如大量出现 Action 泛型错误,说明 migration 脚本漏掉;手动补 <HTMLElement, YourType>。

进一步 v5 迁移在 svelte-runes / svelte-misc 中;本技能只覆盖 Svelte 4 升级。

Quick Fixes

问题解决
数组 .push() 不更新items = [...items, newItem] 或 items = items
slot 样式不生效样式隔离 scoped,不影响 slot 内容
$$restProps 类型错误确认是 export let 而非 let
EventDispatcher 类型问题升级 TypeScript 到 5+

FAQ

Q: 什么时候必须用 Legacy API? A: 维护未迁移的 Svelte 4 项目时。新项目应使用 Runes。

Q: 可以混合使用 Legacy 和 Runes 吗? A: 可以。一个组件使用 $state 即进入 Runes Mode,未使用的部分用 Legacy 语法。

Q: $: 和 $derived 的区别? A: 功能相似,但 $derived 是 Svelte 5 的 Runes API,更显式和可控。$: 在 Legacy Mode 可用。

Q: Slot 和 Snippet 哪个更好? A: Snippets 更强大灵活。Slot 适合简单内容传递;Snippet 可接收参数、可在定义处使用、类型安全更好。

相互参照

このスキルは Svelte Legacy の保守専用で、以下のスキルと連携します。

  • Svelte 5 のエントリーポイントと学習パス → svelte-awesome スキルに引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-awesome。
  • Svelte 4 → Svelte 5 の移行対応表 → svelte-misc スキル(migration 章)に引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-misc。
  • Runes のリアクティビティ($state / $derived / $effect)→ svelte-runes スキルに引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-runes。
  • Stores(writable / readable / derived)→ svelte-lifecycle スキルに引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-lifecycle。
  • テンプレート構文(snippet / event / bind)→ svelte-template-syntax スキルに引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-template-syntax。
  • リアクティビティが更新されない問題のデバッグ / $inspect → svelte-lifecycle スキルに引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-lifecycle。
  • コンポーネントを Web Component にコンパイルする → svelte-misc スキル(Custom Elements 章)に引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-misc。
  • 初期化と移行スクリプト → svelte-cli スキル(sv migrate svelte-5)に引き継ぎます。インストール:npx skills add full-stack-skills/svelte-skills --skill svelte-cli。

例

Legacy API を使った実践的な例:

参考資料

リファレンスドキュメント一式:

コメント