mcpField
S
svelte-misc

svelte-misc

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

svelte-misc について

Svelte 5 開発者向けのリファレンススキルです。TypeScript、カスタムエレメント、ブラウザー対応、推奨パターン、Svelte 4 からの移行情報をまとめています。

主な機能

  1. 01TypeScript の高度な型とコンポーネントパターン
  2. 02カスタムエレメントとライフサイクルの解説
  3. 03ブラウザー対応と機能別の例外
  4. 04Svelte 5 のリアクティビティ推奨パターン
  5. 05Svelte 4 から 5 への移行ガイド

活用シーン

  1. 01ジェネリックまたはラッパーコンポーネントの型付け
  2. 02Web Components の構築
  3. 03対象ブラウザーでの機能対応確認
  4. 04Svelte 4 プロジェクトの段階的な移行

インストール

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

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

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

同梱ファイル

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

agents/
openai.yaml
examples/
best-practices.md
browser-support.md
custom-elements.md
debug-html.md
dynamic-components.md
migration-v4.md
README.md
typescript-advanced.md
typescript.md
references/
best-practices.md
browser-support.md
custom-elements.md
dynamic-reference.md
README.md
typescript-advanced.md
typescript-reference.md

詳細

Svelte Misc Reference (Svelte 5)

このスキルでは、Svelte 5 の TypeScript 高度なサポート、カスタム要素(Web Components)、ブラウザー互換性マトリックス、Svelte 4→5 移行ガイド、公式ベストプラクティス、よくある質問を扱います。

このスキルを使う場面

ユーザーが TypeScript の型注釈(ジェネリクス、ラッパーコンポーネント、DOM 型の拡張)を必要とする場合、$host() / $bindable / extend を使ってカスタム Web コンポーネントを作成する場合、ブラウザー互換性マトリックスと機能ごとの例外を確認する場合、Svelte 4 から Svelte 5 に移行する場合、または Svelte 5 推奨の $state / $derived / $effect パターンに従う場合に、このスキルを使用します。


重要:TypeScript 高度な機能

Svelte は TypeScript をネイティブでサポートしています(Vite プロジェクトでは設定不要です)。<script lang="ts"> で型注釈を有効にします。enum/パラメーター・プロパティなどの実行時機能が必要な場合は、プリプロセッサーが必要です。

<script lang="ts">
  let name: string = 'world';
  function greet(name: string) { alert(`Hello, ${name}!`); }
</script>
<button onclick={(e: Event) => greet((e.target as HTMLElement).innerText)}>
  {name}
</button>

lang="ts" がデフォルトでサポートするのは、「型だけが消去される」機能(注釈、インターフェース、ジェネリクス)のみです。実行時のコード機能(enum、private foo = 1 形式のパラメーター・プロパティ)には、vitePreprocess({ script: true }) の設定が必要です。

Props の型指定と透過
<script lang="ts">
  import type { Snippet } from 'svelte';
  interface Props {
    requiredProperty: number;
    optionalProperty?: boolean;
    snippetWithStringArgument: Snippet<[string]>;
    eventHandler: (arg: string) => void;
    [key: string]: unknown; // 配合 ...rest 透传其他属性
  }
  let { requiredProperty, optionalProperty, snippetWithStringArgument,
        eventHandler, ...rest }: Props = $props();
</script>
ジェネリックコンポーネント

<script> の generics 属性では、関数のジェネリクスと同じ構文を使用できます。

<script lang="ts" generics="Item extends { text: string }">
  interface Props { items: Item[]; select(item: Item): void; }
  let { items, select }: Props = $props();
</script>
{#each items as item}
  <button onclick={() => select(item)}>{item.text}</button>
{/each}
ラッパーコンポーネント(ネイティブ属性の転送)
<script lang="ts">
  import type { HTMLButtonAttributes } from 'svelte/elements';
  let { children, ...rest }: HTMLButtonAttributes = $props();
</script>
<button {...rest}>{@render children?.()}</button>

専用のインターフェースがない要素には、SvelteHTMLElements['div'] 形式を使用します。Component / ComponentProps<T> は、動的コンポーネントの制約や既存コンポーネントの props の抽出に使用します。

クラス内の $state
class Counter {
  count = $state() as number; // 无初值类型会扩为 undefined
  constructor(initial: number) { this.count = initial; }
  increment() { this.count += 1; }
}
svelte/elements の拡張
/// file: additional-svelte-typings.d.ts
declare module 'svelte/elements' {
  export interface SvelteHTMLElements { 'custom-button': HTMLButtonAttributes; }
  export interface HTMLAttributes<T> { globalattribute?: string; }
}
export {}; // 必须——否则会覆盖原模块

重要:カスタム要素(Web Components)

基本的な使い方
<svelte:options customElement="my-element" />
<script>
  let { name = 'world' } = $props();
</script>
<h1>Hello {name}!</h1>
<slot />

インポートすると自動的に customElements.define() が登録されます。利用側では DOM 属性を読み書きできます。

const el = document.querySelector('my-element');
el.name = 'everybody'; // 触发 shadow DOM 更新

props を明示的に宣言する必要があります(let props = $props() だけでは不十分です)。そうしないと、Svelte は公開するキーを認識できません。

customElement オプション
<svelte:options customElement={{
  tag: 'my-counter',
  shadow: 'open',
  props: { count: { type: 'Number', reflect: true, attribute: 'start' } },
  extend: (Ctor) => class extends Ctor { /* ... */ }
}} />
フィールド値デフォルト役割
tagstring—タグ名。設定すると自動登録されます
shadow'none' | 'open' | 'closed' | ShadowRootInit'open'Shadow root の設定
props.<name>.attributestring小文字の prop 名カスタム属性名
props.<name>.reflectbooleanfalseprop の値を HTML 属性に反映します
props.<name>.type'String' | 'Boolean' | 'Number' | 'Array' | 'Object''String'属性 ↔ prop の型変換
extend(Ctor) => class—生成されたクラスをラップします(ライフサイクル/ElementInternals を注入できます)
$host() Rune とライフサイクル
<svelte:options customElement="tooltip" />
<script>
  import { $host } from 'svelte';
  let { text = 'hi' } = $props();
  function focus() { $host().focus(); }
</script>
<button onclick={focus}>{text}</button>
  • 内部コンポーネントは connectedCallback の後、次の tick に作成されます。挿入前に設定した属性はバッファリングされ、適用されます。
  • Shadow DOM の更新は次の tick までバッチ処理されます。DOM の移動によって不要なアンマウントは発生しません。
  • disconnectedCallback の後、次の tick に破棄されます。コンポーネントのメソッドはマウント後にのみ使用できます。より早く公開するには、extend クラス内で宣言してください。
重要な注意事項
  • スタイルは「スコープ化」ではなくカプセル化されます。グローバル CSS は shadow root を通過できません。
  • CSS は個別の .css ファイルではなく、JS 文字列としてインライン化されます。
  • SSR には適していません(JS の読み込み前は shadow DOM が表示されません)。
  • スロットの内容は積極的にレンダリングされます(Svelte のデフォルトの遅延レンダリングとは異なります)。{#each} 内の <slot> では内容は複製されません。
  • let: ディレクティブはカスタム要素では機能しません。Svelte の context はカスタム要素の境界を越えられません。
  • on* 属性はイベントリスナーとして解釈されるため、名前に使用しないでください。

重要:ブラウザーサポート

Svelte 5 の対象は Baseline 2020 です。

ブラウザー最低バージョン
Chrome / Edge87
Firefox83
Safari14
Opera73
Opera (Android)62
Samsung Internet14.0
Android WebView87
Internet Explorer非サポート
例外
機能Chrome/EdgeFirefoxSafari
$state.snapshot989415.4
bind:devicePixelContentBoxSize—93非サポート
flip(svelte/animate 由来)—126—
SSR でのブラウザー API 保護
<script>
  import { onMount } from 'svelte';
  onMount(() => {
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  });
</script>

<svelte:window> / <svelte:document> を優先してください。Svelte が SSR とアンマウントを自動的に処理します。


重要:ベストプラクティス

$state — 必要なときだけ宣言する

更新をトリガーする値($effect / $derived / テンプレート)のみを $state として宣言します。再代入のみを行う大きなオブジェクト(API レスポンス)には、Proxy のオーバーヘッドを避けるため $state.raw を使用します。

let user = $state.raw<User | null>(null);
純粋な計算には $effect より $derived
let square = $derived(num * num); // 好
// let square; $effect(() => { square = num * num; }); // 差

複雑なロジックには $derived.by(() => { ... }) を使用します。Derived は書き込み可能です。オブジェクト/配列の結果は深くプロキシ化されません。

$effect はエスケープハッチです

優先するツール:外部ライブラリーとの同期 → {@attach ...}、ユーザー入力への応答 → ハンドラー、デバッグログ → $inspect / $inspect.trace、外部ソースの監視 → createSubscriber。effect はサーバーでは実行されないため、effect を if (browser) { ... } で囲まないでください。

Props は変化するものとして扱い、イベントには属性構文を使う
let { type } = $props();
let color = $derived(type === 'danger' ? 'red' : 'green');

グローバルイベントのリスナーには <svelte:window> / <svelte:document> を使用します。onMount で手動バインドしないでください。Slots の代わりに Snippets を使用し、{#each ... (item.id)} では安定したキーを使います(index は使用不可)。style:-- で JS 変数を CSS カスタムプロパティに渡します。子コンポーネントのスタイルを通過させるには :global ではなく CSS 変数を使用します。モジュールレベルの共有状態の代わりに createContext を使用します(型安全性を確保し、SSR でユーザー間の情報漏えいを防ぎます)。

新しいコードでは Legacy を避ける

on:click → onclick;export let → $props();$: → $derived / $effect;<slot> → snippet;use:action → {@attach ...}。


重要:Svelte 4 移行ガイド

最小バージョン
依存関係要件
Node16+
SvelteKit1.20.4+(使用する場合)
vite-plugin-svelte2.4.1+
TypeScript5+
核心迁移对照
Svelte 4Svelte 5
let x = 0(顶层响应式)let x = $state(0)
$: x = a + blet x = $derived(a + b)
$: { ... }$effect(() => { ... })
export let proplet { prop } = $props()
<slot />{@render children()}
createEventDispatchercallback props
on:click={fn}onclick={fn}
自动迁移工具
npx svelte-migrate@latest svelte-5 my-project
重要行为变化
  • 转换默认 local(外层控制流不影响子 transition)。
  • 默认插槽绑定不会进入具名插槽。
  • 预处理器顺序:markup → script → style(按声明顺序逐个执行)。
  • createEventDispatcher 严格模式下检查可选 / 必传 / 无参类型(之后用 callback props 替代)。
  • Action / ActionReturn 默认参数类型为 undefined,需要参数时显式声明。
  • SvelteComponentTyped 已弃用,统一用 SvelteComponent。
  • CJS 输出与 svelte/register 被移除。
  • 删除 svelte.JSX,改用 svelteHTML / svelte/elements。
  • 打包器必须指定 browser 条件(SvelteKit / Vite 自动;Rollup 用 @rollup/plugin-node-resolve 设 browser: true;Webpack 在 conditionNames 加 "browser")。

Critical: Svelte 5 Migration Guide (Concept Summary)

Runes 系统:$state / $derived / $effect 替代隐式响应式;Snippets 替代 Slots;事件属性替代 on:;$effect 显式追踪依赖;$state 对对象/数组做深层 Proxy。

移除替代
let 顶层隐式响应式$state
$: 语句$derived / $effect
export let / $$props / $$restProps$props()
createEventDispatchercallback props / $bindable
SlotsSnippets
on:eventonevent
beforeUpdate / afterUpdate$effect.pre / $effect

新增:$state.eager、$effect.pre、$effect.tracking、$state.snapshot、hydratable、fork()、{#key} 过渡触发、<svelte:boundary>、createContext。


FAQ

Q: Svelte 和 Vue/React 的核心区别? A: Svelte 无虚拟 DOM——编译时生成精确 DOM 更新代码,运行时零框架开销。

Q: Svelte 5 和 Svelte 4 可以共存吗? A: 可以。Svelte 5 仍支持 Legacy Mode,Svelte 4 的 $: 与 export let 可继续用;可在同一项目渐进迁移。

Q: 如何升级到 Svelte 5? A: ① 升级 svelte + sveltekit / vite-plugin-svelte;② 跑 npx svelte-migrate@latest svelte-5;③ 逐步迁到 Runes Mode。

Q: Svelte 支持 SSR / TypeScript 吗? A: 都原生支持。SSR 用 render() 或 SvelteKit;TS 直接用 <script lang="ts">,CI 跑 svelte-check。

Q: Svelte 有虚拟 DOM 吗? A: 没有。Svelte 编译器生成精确 DOM 操作代码(element.textContent = ...),而非通过 vDOM diffing。

Q: 哪些浏览器支持 Svelte 5? A: Baseline 2020(Chrome / Edge 87+、Firefox 83+、Safari 14+)。不支持 IE;少数功能需更高版本(见上表)。

Q: 自定义元素的样式如何控制? A: 默认 shadow root 模式 'open',全局 CSS 不会穿透。可用 shadow: 'none' 继承全局样式;用 CSS 变量穿透 scoped 样式。


Quick Fixes

问题解决方案
Svelte 4 代码报错确认组件未使用 $state(进入 Runes Mode)
$: 不生效升级到 Svelte 5,Legacy Mode 仍支持
TypeScript 报错确认 <script lang="ts"> 和 TypeScript 5+
迁移后打包变大检查 tree-shaking 配置
属性以 on 开头被监听重命名避免 on* 前缀
自定义元素 SSR 没内容预渲染不支持 shadow DOM;等 JS 加载
generic component 类型报错检查 generics 字符串(与函数泛型同语法)

Gotchas

  1. Svelte 5 自动进入 Runes Mode — 只要使用了任何 Rune($state 等)即为 Runes Mode。
  2. Legacy Mode — 可通过 <svelte:options runes={false}> 强制启用。
  3. on:click 已废弃 — Legacy Mode 仍可用,但会警告。
  4. createEventDispatcher 已弃用 — 新代码用 callback props。
  5. $bindable(default) — 仅在父组件未传 prop 时作 fallback;父组件传 undefined 会保留 undefined。
  6. bind:this 泛型组件 — 实例类型为 Component<Props> | null,需要断言。
  7. 自定义元素 inline CSS — 没有可被外部样式表链接的 .css 文件。
  8. 服务端 effect 不运行 — 不要用 if (browser) 包 effect 主体。

例

Svelte 5 の機能を実際に使った例です。

  • 動的コンポーネント:svelte:element と {#key} ブロック
  • デバッグと HTML:@html、@debug、@const
  • TypeScript:
    • TypeScript の基本 — 型付き props、ジェネリクス、イベントハンドラー、コンポーネント参照
    • TypeScript の応用 — 14 のパターン:プリプロセッサ、ジェネリック制約、ラッパーコンポーネント、Component 型、クラス内の $state、svelte/elements の拡張、svelte-check、$bindable、フォームの状態
  • カスタム要素:カスタム要素 — 12 のパターン:customElement オプション、$host()、型変換、リフレクション、extend、ElementInternals、スロットのセマンティクス
  • ベストプラクティス:Svelte 5 のベストプラクティス — 14 のパターン:$state.raw、$derived.by、キー付き each ブロック、CSS 変数、createContext、非同期 Svelte、レガシー機能の置き換え
  • 移行:Svelte 3→4 の移行 — 10 のパターン:tag → customElement、より厳格な型、トランジションのスコープ、プリプロセッサの順序、CJS の削除
  • ブラウザーサポート:ブラウザーサポート — 7 のパターン:機能検出、ポリフィル、バンドラーのターゲット、SSR ガード、$state.snapshot のフォールバック、Playwright のバージョン固定

リファレンス

詳細なリファレンスドキュメントです。

  • 動的コンポーネント:動的コンポーネントのリファレンス — svelte:element、{#key}、{@html}、@debug、@const
  • TypeScript:
  • カスタム要素:カスタム要素 — customElement の API、$host() ルーン、ライフサイクル、注意点、ElementInternals
  • ベストプラクティス:ベストプラクティス — $state / $derived / $effect、props、イベント、スニペット、each ブロック、CSS 変数、コンテキスト、非同期処理
  • ブラウザーサポート:ブラウザーサポート — 最低バージョンの一覧、機能ごとの例外、ポリフィル、SSR の安全性、バンドラーの設定
Quick Links
FeatureReference
svelte:elementDynamic Components
{#key}Dynamic Components
{@html} / @debug / @constDynamic Components
TS basicsTypeScript Basics
TS advancedTypeScript Advanced
Generic componentsTypeScript Advanced
Wrapper componentsTypeScript Advanced
Component typeTypeScript Advanced
DOM augmentationTypeScript Advanced
customElement optionsCustom Elements
$host() runeCustom Elements
Web Component lifecycleCustom Elements
$state / $derived / $effect patternsBest Practices
Async SvelteBest Practices
Browser matrixBrowser Support
Feature exceptionsBrowser Support
PolyfillsBrowser Support

コメント