svelte-special-elements について
Svelte Special Elements Reference は、Svelte 5 の特殊なテンプレート要素を扱う開発者向けのスキル兼リファレンスです。エラーや待機状態の境界、ブラウザーイベント要素、head への挿入、動的タグ、コンパイラーオプションと、関連する SSR の動作を解説します。
主な機能
- 01エラー/待機状態の境界
- 02window・document・body のイベント
- 03head の内容とメタデータ
- 04動的な HTML 要素
- 05コンパイラーオプションとカスタム要素
- 06SSR の動作とエラー変換
活用シーン
- 01描画エラーや初回の非同期読み込みに代替表示を用意
- 02ブラウザーイベントとバインディングを処理
- 03ページのメタデータと構造化データを設定
- 04実行時に選ばれたタグを描画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ full-stack-skills/ svelte-skills --skill svelte-special-elementsインストール後、Claude Code で/svelte-special-elementsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlexamples/boundary-examples.mdREADME.mdsvelte-element-examples.mdsvelte-head-examples.mdreferences/boundary-reference.mdREADME.mdsvelte-element-reference.mdsvelte-head-reference.mdsvelte-options-reference.mdsvelte-window-document-body-reference.md詳細
Svelte 特殊要素リファレンス(Svelte 5)
このスキルでは、エラー境界、非同期読み込み状態、window/document/イベントのリスニング、動的タグ、head への挿入、コンパイラーオプションなどの用途で使用する、Svelte テンプレート内の特殊要素(svelte: プレフィックス付き)を扱います。
このスキルを使用する場面
レンダリングエラーや非同期の pending 状態(<svelte:boundary>)を捕捉する、window/document/body のイベントをリッスンする、HTML タグを動的にレンダリングする(<svelte:element>)、内容を document.head に挿入する(<svelte:head>)、またはコンパイラーオプション/カスタム要素を設定する(<svelte:options>)場合に使用します。
重要:<svelte:boundary>(Svelte 5.3+)
エラーと非同期処理の境界です。アプリケーションの一部を「隔離」して、エラーや pending 状態を処理します。この境界は、レンダリング中にスローされた同期エラー、$effect 内のエラー、await 式の rejection を捕捉します。イベントハンドラー、setTimeout、イベントによってトリガーされる非同期処理など、レンダリングフロー外のエラーは捕捉されません。
重要な 3 つのプロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
pending | Snippet | 初回レンダリング時に表示され、すべての await が解決するまで維持されます(初回レンダリング時のみ表示) |
failed | Snippet<[error, reset]> | エラー発生時に表示され、error と、復旧に使用できる reset 関数を受け取ります |
onerror | (error, reset) => void | エラー発生時に呼び出されます。Sentry などへの報告によく使用されます。failed と並行して実行されます |
<svelte:boundary onerror={(e) => report(e)}>
<FlakyComponent />
{#snippet pending()}
<p>加载中…</p>
{/snippet}
{#snippet failed(error, reset)}
<button onclick={reset}>oops! try again</button>
{/snippet}
</svelte:boundary>
SSR:transformError(Svelte 5.51+)
デフォルトでは、エラー境界はサーバー側では機能しません。レンダリングエラーが発生すると、render(...) 呼び出し全体が失敗します。5.51 以降では、render(...)/mount(...)/hydrate(...) に transformError 関数を渡せます。この関数は、failed スニペットでレンダリングするための JSON-stringifiable なオブジェクトを返す必要があります(SSR 時に HTML にシリアライズされ、クライアント側でデシリアライズされた後、水和に使用されます)。
import { render } from 'svelte/server';
const { head, body } = await render(App, {
transformError: (error) => {
console.error(error); // 保留原始错误用于日志
return { message: 'An error occurred!' }; // 返回脱敏后的安全对象
}
});
onerror で再スローする
onerror 内でエラーをスローする(または元のエラーを再スローする)と、そのエラーは外側の境界によって捕捉されます。これを利用すると、現在の failed UI を維持しながら、エラーをグローバル境界に報告できます。
reset のモード
reset は通常の関数です。state に保存して、境界外のグローバル UI やキーボードショートカットなど、任意の場所から呼び出せます。
<script>
let error = $state(null);
let reset = $state(() => {});
function onerror(e, r) { error = e; reset = r; }
</script>
<svelte:boundary {onerror}>
<FlakyComponent />
</svelte:boundary>
{#if error}
<button onclick={() => { error = null; reset(); }}>oops! try again</button>
{/if}
完全な例とリファレンス:examples/boundary-examples.md、references/boundary-reference.md
重要:<svelte:window>
window イベントをリッスンし、window プロパティにバインドします。
<svelte:window onkeydown={handleKey} onresize={handleResize} />
<svelte:window bind:scrollX bind:scrollY bind:innerWidth bind:innerHeight />
バインド可能なプロパティ:
| プロパティ | 型 | 読み取り専用 | 説明 |
|---|---|---|---|
innerWidth / innerHeight | number | はい | ビューポートの幅/高さ(CSS ピクセル) |
outerWidth / outerHeight | number | はい | ブラウザーウィンドウの外側のサイズ(chrome を含む) |
scrollX / scrollY | number | いいえ | スクロール位置(書き込み可能な唯一の window バインディング) |
online | boolean | はい | navigator.onLine のエイリアス |
devicePixelRatio | number | はい | 現在のディスプレイの device pixel ratio |
リッスン可能なイベント:すべての window レベルのイベント。キーボード(onkeydown / onkeyup)、マウス(onclick / onmousemove など)、タッチ(ontouchstart / ontouchmove)、ポインター(onpointerdown など)、ホイール(onwheel)、クリップボード(oncopy / oncut / onpaste)、ドラッグ(ondrag 系列)、フォーカス(onfocus / onblur)、リソース(onload / onerror / onscroll / onresize)などがあります。
<svelte:window>はコンポーネントのトップレベルにのみ配置でき、ブロック要素内や条件ブロック内には配置できません。初回マウント時に、ページが
scrollX/scrollYの初期値までスクロールすることはありません(アクセシビリティへの配慮によるものです)。スクロールが発生するのは、以降に値が変更された場合のみです。マウント直後にスクロールするには、$effect内でscrollTo()を呼び出してください。
重要:<svelte:document>
document レベルのイベント(window ではサポートされていないイベント)をリッスンします。
<svelte:document onvisibilitychange={handleVisibility} />
<svelte:document {@attach myAttachment} />
バインド可能なプロパティ(すべて readonly):
| プロパティ | 型 | 説明 |
|---|---|---|
activeElement | Element | null | 現在フォーカスされている要素 |
fullscreenElement | Element | null | 現在の全画面要素 |
pointerLockElement | Element | null | ポインターロックされている要素 |
visibilityState | 'visible' | 'hidden' | ドキュメントの表示状態 |
よく使用されるイベント:onvisibilitychange(タブの切り替え)、onselectionchange(テキスト選択の変更)、onreadystatechange、onfullscreenchange、onpointerlockchange、oncopy / oncut / onpaste など。
<svelte:document>もトップレベルにのみ配置できます。{@attach ...}を使ってdocumentにカスタム動作を追加できます。
重要:<svelte:body>
body 要素のイベント(mouseenter、mouseleave など、window 上では発生しないイベント)をリッスンします。
<svelte:body onmouseenter={handleMouseenter} onmouseleave={handleMouseleave} use:someAction />
<svelte:body>はuse:action もサポートしています(<body>に action を追加する唯一のすっきりとした方法です)。こちらもトップレベルにのみ配置できます。
Critical: <svelte:head>
向 document.head 插入内容;SSR 时单独暴露于 body 之外,框架会把 head 内容放进 HTML <head> 标签。
<svelte:head>
<title>Hello world!</title>
<meta name="description" content="SEO description" />
<meta property="og:title" content="OG title" />
<link rel="canonical" href="/current-url" />
</svelte:head>
支持元素:
| 元素 | 用途 |
|---|---|
<title> | 文档标题 |
<meta> | SEO(name="description")、Open Graph(property="og:...")、Twitter Card、robots 指令 |
<link rel="stylesheet" /> | 按页/按主题样式表 |
<link rel="canonical" /> | 规范 URL |
<link rel="prefetch" | rel="preload" /> | 资源预取/预加载 |
<style> | 内联关键 CSS |
<script type="application/ld+json"> | JSON-LD 结构化数据 |
关键行为:
- 响应式:
$state/$derived变化时 head 自动更新。 - 重复合并:同种元素(如两个
<title>)后渲染的会覆盖前一个(不重复追加)。 - 多个块:同一组件内可有多个
<svelte:head>,全部合并到 head。 - SSR 单独暴露:
render()返回{ head, body },框架需要把head放进<head>标签。
完整示例:examples/svelte-head-examples.md、references/svelte-head-reference.md
Critical: <svelte:element>
动态渲染未知标签(如来自 CMS 或数据库):
<script>
let tag = $state('hr');
</script>
<svelte:element this={tag}>内容</svelte:element>
<svelte:element this={tag} xmlns="http://www.w3.org/2000/svg" />
行为规则:
this为null/undefined→ 元素不渲染this为 void 元素(br、hr、img等)但有子元素 → 开发模式下运行时错误- Svelte 自动推断 namespace(svg、mathml),可用
xmlns显式指定 this必须是合法的 DOM 标签名(如div/circle);#text、svelte:head等无效
唯一支持的绑定:bind:this(因为通用元素不支持 Svelte 内建绑定如 bind:value)
Critical: <svelte:options>
设置编译器选项:
<svelte:options runes={true} />
<svelte:options namespace="svg" />
<svelte:options customElement="my-element" />
<svelte:options css="injected" />
| 选项 | 类型 | 说明 |
|---|---|---|
runes={true|false} | boolean | 强制进入/退出 Runes Mode |
namespace="html|svg|mathml" | string | 组件命名空间(默认 html) |
customElement={...} | string | object | 编译为自定义元素(字符串即 tag) |
css="injected" | string | 样式内联注入(SSR → style 标签;CSR → JS) |
<svelte:options>必须放在<script>之后、模板之前。
Legacy(已弃用)选项(在 Runes 模式下无效):immutable={true|false}、accessors={true|false}。
Quick Fixes
| 问题 | 解决方案 |
|---|---|
想监听 visibilitychange / selectionchange | 用 <svelte:document> 而非 <svelte:window> |
想监听 mouseenter / mouseleave | 用 <svelte:body> |
| 动态标签不渲染 | 检查 this 是否为 nullish |
| 样式不生效 | 用 css="injected" 强制内联 |
| 渲染抛错整个应用挂掉 | 用 <svelte:boundary> + failed 片段隔离 |
| 异步加载时显示骨架屏 | 用 <svelte:boundary> + pending 片段(仅首次渲染) |
| 渲染时想上报到 Sentry | 用 <svelte:boundary onerror={...}> |
想让 reset 在边界外触发 | 把 error / reset 存到 $state |
动态改 <title> 或 <meta> | 用 <svelte:head> 包裹响应式表达式 |
Gotchas
- 只能出现在顶层 —
svelte:window/document/body/head/element不能在{#if}或其他块级元素内。 - SSR 行为不同 —
<svelte:head>在 SSR 时内容单独暴露,不在 body 内;<svelte:boundary>默认对 SSR 无效(5.51+ 起可用transformError启用)。 svelte:element是通用绑定 — 不支持bind:value等元素特有绑定。svelte:window的scrollX/scrollY是唯一可写绑定 — 其他都 readonly。<svelte:boundary>不捕获事件处理器 /setTimeout中的错误 — 这些不是渲染流程。<svelte:boundary>的pending只在初次渲染显示 — 后续异步更新用$effect.pending()。
FAQ
Q: <svelte:boundary> 和 try/catch 有什么区别?
A: svelte:boundary 捕获渲染时的同步/异步错误和 $effect 中的错误;try/catch 只能捕获同步错误。boundary 还可配合 {#snippet pending} 处理初次异步加载状态。
Q: 什么时候用 onerror,什么时候用 failed?
A: failed 是 UI——决定出错时显示什么;onerror 是副作用——决定出错时做什么(如上报到 Sentry)。两者完全独立,可以只用其一,也可以同时使用。
Q: svelte:element 和普通组件有什么区别?
A: svelte:element 渲染 HTML 标签(不是 Svelte 组件),适用于标签在运行时才确定的场景,如 CMS 内容。
Q: 什么时候用 namespace="svg"?
A: 当组件会作为 SVG 子元素被使用时(如 <Icon.svelte> 作为 <svg> 内 <g> 使用)。
Q: mount / hydrate / render 怎么传 transformError?
A: 都是同一签名——传一个 (error) => JSON-stringifiable-object 的函数:
import { mount, hydrate } from 'svelte';
import { render } from 'svelte/server';
mount(App, { target, transformError: (e) => ({ message: e.message }) });
hydrate(App, { target, transformError: (e) => ({ message: 'Hydration failed' }) });
const { head, body } = await render(App, { transformError: (e) => ({ message: '...' }) });
Q: 可以在多个组件中用同一个 <svelte:head> 块吗?
A: 不行——<svelte:head> 是组件级的作用域。但你可以把 head 内容拆成 snippet,在多个组件中分别引入,或者封装一个 <MetaTags> 组件。
Q: <svelte:window> 的事件处理器会影响性能吗?
A: onresize / onscroll 这类高频事件建议做节流/防抖;其他事件开销可忽略。Svelte 会在组件销毁时自动移除监听器,无需手动清理。
例
svelte:特殊要素のすべてを実演する実践的な例です。
| ファイル | 説明 |
|---|---|
| examples/boundary-examples.md | <svelte:boundary>の包括的な例:pending、failed、onerror、transformError、エラー報告、ネストされた境界 |
| examples/svelte-head-examples.md | <svelte:head>の例:SEOメタデータ、Open Graph、構造化データ、動的スタイルシート、SSRでのhead抽出 |
| examples/svelte-element-examples.md | <svelte:window>、<svelte:document>、<svelte:body>、<svelte:element>、<svelte:component>、<svelte:self>、<svelte:options>の例 |
クイック例
- svelte:boundary:エラー時のフォールバック、読み込み中のスケルトン、Sentryへの報告、SSRの
transformError - svelte:window:キーボードショートカット、リサイズ処理、スクロール位置のバインド
- svelte:document:ページの表示状態、テキスト選択の追跡
- svelte:body:マウスの進入/離脱イベント
- svelte:head:動的な
<title>、Open Graphメタデータ、JSON-LD、ページごとのスタイルシート - svelte:element:動的な見出しレベル(h1-h6)、条件付きタグ、SVG名前空間
- svelte:component:動的なコンポーネントの切り替え
- svelte:options:customElement、runesモード、SVG名前空間
リファレンス
すべての特殊要素とコンパイラーオプションの詳細なリファレンスドキュメントです。
| ファイル | 説明 |
|---|---|
| references/boundary-reference.md | <svelte:boundary>の完全なリファレンス — pending/failed/onerror、transformError(5.51+)、ネスト、捕捉されるもの/されないもの |
| references/svelte-head-reference.md | <svelte:head>の完全なリファレンス — SSRの動作、サポートされる要素、ハイドレーション、リアクティビティ |
| references/svelte-window-document-body-reference.md | <svelte:window>/<svelte:document>/<svelte:body>のすべてのイベントとバインド可能なプロパティ |
| references/svelte-element-reference.md | <svelte:element>、<svelte:component>、<svelte:self>、<svelte:fragment>のリファレンス |
| references/svelte-options-reference.md | <svelte:options>の完全なリファレンス — customElement、runes、namespace、css、およびすべてのコンパイラーオプション |