API Docs

始める前に

このページには、API リファレンスの詳細なドキュメントが含まれています。これは既に Svelte にある程度親しんでいる人のためのリソースとなることを意図しています。

もしあなたが(まだ)そうでないのであれば、このリファレンスを参照する前に 対話型チュートリアル例題 を参照することをお勧めします。

恥ずかしがらずにDiscord chatroomで助けを求めましょう。

古いバージョンのSvelteをお使いですか? v2 docsをご覧ください。

日本語翻訳版 追記:上記のDiscordはSvelte本体のもので、英語でコミュニケーションが行われています。もし日本語で質問したり交流したいのであれば、Svelte日本のDiscordにどうぞ!

Component format

コンポーネントは、Svelteアプリケーションを構成するブロックです。これらは .svelte ファイルにHTMLのスーパーセットを使って記述されます。

ここで説明される script 、 style 、マークアップのいずれもコンポーネントに必須のものではありません。

<script>
	// ロジックを記述
</script>

<style>
	/* styleを記述 */
</style>

<!-- 0個以上のマークアップを記述 -->

<script>

<script> ブロックは、コンポーネントのインスタンスが生成されるときに実行される JavaScript を含みます。トップレベルで宣言(またはインポート)された変数は、そのコンポーネントのマークアップから '見る' ことができます。 <script> には、4つのルールがあります。

1. export creates a component prop

Svelte では、 変数の宣言を プロパティprop)としてマークするために export キーワードを使います。これによってそのコンポーネントを使用する際にその変数にアクセスできるようになります(より詳しい情報は 属性とプロパティを見てください)。

<script>
	export let foo;

	// プロパティとして渡された変数は、
	// 即座に使用可能になります
	console.log({ foo });
</script>

プロパティはデフォルトの初期値を指定することができます。これはコンポーネントの初期化時にプロパティが指定されていない場合(または初期値が undefined の場合)に使用されます。プロパティを削除すると、その値は初期値ではなく undefined になることに注意してください。

development モード(コンパイラオプションを参照)では、 デフォルトの初期値が指定されておらず、使用時に値を指定していない場合警告が表示されます。この警告を解消するためには、たとえ undefined であってもデフォルトの初期値を指定してください。

<script>
	export let bar = 'optional default initial value';
	export let baz = undefined;
</script>

constclassfunction をエクスポートすると、コンポーネントの外からは読み取り専用になります。ただし、関数は有効なプロパティです。

<script>
	// これらは読み取り専用です
	export const thisIs = 'readonly';

	export function greet(name) {
		alert(`hello ${name}!`);
	}

	// これはプロパティです
	export let format = n => n.toFixed(2);
</script>

予約語もプロパティの名前として使用することができます。

<script>
	let className;

	// `class` は予約語ですが、
	// `class` プロパティを作ることができます
	export { className as class };
</script>
2. 代入は'リアクティブ'

コンポーネントの状態を変更して再レンダリングをトリガーするために必要なのは、ローカルで宣言された変数に代入することだけです。

更新式 (count += 1) とプロパティの代入 (obj.x = y) には同じ効果があります。

Svelteのリアクティビティは代入に基づいているため、.push().splice() のような配列のメソッドを使用しても自動的に更新をトリガーしません。これを回避する方法はチュートリアルに記載しています。

<script>
	let count = 0;

	function handleClick () {
		// マークアップが `count` を参照している場合、
		// この関数を呼び出すと更新がトリガーされます
		count = count + 1;
	}
</script>
3. $: はステートメントがリアクティブであることを示す

トップレベルの(つまりブロック内や関数内でない)ステートメントは $: という JS ラベル構文 の接頭辞をつけることでリアクティブにできます。リアクティブステートメントは、依存する値が変更されるたびに、コンポーネント更新の直前に実行されます。

<script>
	export let title;

	// これは `title` プロパティが変わるたびに
	// `document.title` を更新します
	$: document.title = title;

	$: {
		console.log(`複数のステートメントをまとめることができます`);
		console.log(`現在のタイトルは ${title}`);
	}
</script>

$: のブロック内に直接現れる値だけが、リアクティブステートメントが依存しているものになります。例えば次のコードで totalx が変更された時にのみ更新され、y では更新されません。

<script>
	let x = 0;
	let y = 0;

	function yPlusAValue(value) {
		return value + y;
	}

	$: total = yPlusAValue(x);
</script>

Total: {total}
<button on:click={() => x++}>
	Increment X
</button>

<button on:click={() => y++}>
	Increment Y
</button>

宣言されていない変数への代入だけでステートメントが構成されている場合、Svelte はあなたの代わりに let 宣言を挿入します。

<script>
	export let num;

	// `squared` や `cubed` を宣言する必要はありません
	// — Svelte がやってくれます
	$: squared = num * num;
	$: cubed = squared * num;
</script>
4. ストアに$接頭辞を付けて値にアクセスする

ストアは、シンプルなストアコントラクト(store contract)を介して値へのリアクティブなアクセスを可能にするオブジェクトです。svelte/store モジュールにはこのコントラクト(contract)を満たす最小限のストア実装が含まれています。

ストアへの参照を持っているときはいつでも、$を接頭辞として付けることで、コンポーネント内からその値にアクセスできます。これによってSvelteは接頭辞付きの変数を宣言し、ストアのサブスクリプションを設定します。このサブスクリプションは適切なタイミングで解除されます。

$接頭辞が付いた変数に代入するには、その変数が書き込み可能なストアである必要があります。また、代入時にはストアの .setメソッドが呼び出されます。

ストアはコンポーネントのトップレベルで宣言しなければいけないことに注意してください。例えば、ifブロックや関数の中では宣言できません。

(ストア値を表すものではない)ローカル変数には、$接頭辞を付けてはいけません。

<script>
	import { writable } from 'svelte/store';

	const count = writable(0);
	console.log($count); // logs 0

	count.set(1);
	console.log($count); // logs 1

	$count = 2;
	console.log($count); // logs 2
</script>
ストアコントラクト(Store contract)
store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void }

ストアコントラクト(store contract)を実装することで、svelte/storeに依存せずに独自のストアを作ることができます。

  1. ストアは .subscribe メソッドを含まなければならず、その引数としてサブスクリプション関数を受けとる必要があります。このサブスクリプション関数は .subscribe が呼ばれたらストアの現在の値と同期して即座に呼び出されなければいけません。ストアのアクティブなサブスクリプション関数は全て、ストアの値が変更されるたびに同期して呼び出されなければいけません。
  2. .subscribe メソッドはサブスクリプションを解除する関数を返さなければいけません。サブスクリプションを解除する関数が呼ばれたら、そのサブスクリプションを停止してそれに対応するサブスクリプション関数がそのストアから再び呼び出されないようにしなければいけません。
  3. ストアはオプションで .set メソッドを含むことができます。.set メソッドは、引数としてストアの新しい値を受けとる必要があり、全てのアクティブなサブスクリプション関数を同期的に呼び出します。このようなストアは 書き込み可能なストア (writable store) と呼ばれます。

RxJSのObservablesとの相互運用性のため、.subscribe メソッドはサブスクリプションを解除する関数を直接返すのではなく、.unsubscribe メソッドを持つオブジェクトを返すこともできます。ただし、.subscribe が同期的にサブスクリプションを呼び出さない限り(これはObservableの仕様で要求されていませんが)、サブスクリプションを呼び出すまでは、Svelte がストアの値を undefined とみなすことに注意してください。

<script context="module">

context="module" 属性をもつ <script> タグは、コンポーネントインスタンスごとではなく、モジュールが最初に評価するときに1回実行されます。このブロックで宣言された値は、通常の <script>(およびコンポーネントのマークアップ)からアクセスできますが、その逆はできません。

このブロックからバインディングを export でき、それらはコンパイルされたモジュールのエクスポートになります。

デフォルトのエクスポートはコンポーネント自体であるため、export default はできません。

module スクリプトで定義された変数はリアクティブではありません。つまり、変数の再代入は、変数自体の更新はしますが、再レンダリングのトリガーにはなりません。複数のコンポーネント間で共有される値については、ストアの使用を検討してください。

<script context="module">
	let totalComponents = 0;

	// this allows an importer to do e.g.
	// `import Example, { alertTotal } from './Example.svelte'`
	export function alertTotal() {
		alert(totalComponents);
	}
</script>

<script>
	totalComponents += 1;
	console.log(`total number of times this component has been created: ${totalComponents}`);
</script>

<style>

<style> ブロック内の CSS は、そのコンポーネントにスコープされます。

これは、影響を受ける要素にクラスを追加することで動作し、そのクラスはコンポーネントのスタイルのハッシュに基づいています (例えば svelte-123xyz)。

<style>
	p {
		/* これはこのコンポーネントの <p> 要素にのみ影響します */
		color: burlywood;
	}
</style>

スタイルをグローバルなセレクタに適用するには、:global(...)修飾子を使用します。

<style>
	:global(body) {
		/* これは <body> に適用されます */
		margin: 0;
	}

	div :global(strong) {
		/* これは、このコンポーネント内の <div> 要素の中にある
		   任意のコンポーネント内の <strong> 要素に適用されます */
		color: goldenrod;
	}
</style>

グローバルにアクセスできる @keyframes を作りたい場合は、キーフレーム名の前に -global- を付ける必要があります。

コンパイル時に -global- の部分は削除され、キーフレームはコード内の他の箇所では my-animation-name だけを使って参照されます。

<style>
	@keyframes -global-my-animation-name {...}
</style>

Template syntax

Tags

<div> のような小文字のタグは、通常の HTML 要素を表します。大文字のタグ、例えば <Widget><Namespace.Widget>コンポーネント を表します。

<script>
	import Widget from './Widget.svelte';
</script>

<div>
	<Widget/>
</div>

Attributes and props

デフォルトでは、属性はHTMLと全く同じように動作します。

<div class="foo">
	<button disabled>can't touch this</button>
</div>

HTMLのように、値は引用符で囲まれていない場合があります。

<input type=checkbox>

属性値には JavaScript の式を含めることができます。

<a href="page/{p}">page {p}</a>

あるいは、JavaScript の式にすることもできます。

<button disabled={!clickable}>...</button>

Boolean の属性は、その値が truthy であれば要素に含まれ、falsy であれば除外されます。

それ以外の属性は、その値が nullish (null または undefined) でない限り含まれます。

<input required={false} placeholder="This input field is not required">
<div title={null}>This div has no title attribute</div>

式には、通常の HTML ではシンタックスハイライトに失敗するような文字が含まれている可能性があるので、値を引用符で囲むことが許可されています。引用符は値の解析方法には影響しません。

<button disabled="{number !== 42}">...</button>

属性名と値が一致する場合(name={name})は、{name}で置き換えることができます。

<!-- These are equivalent -->
<button disabled={disabled}>...</button>
<button {disabled}>...</button>

慣習として、コンポーネントに渡される値は DOM の機能である 属性 ではなく、プロパティ または props と呼ばれます。

要素の場合と同様に、name={name}{name} の短縮形に置き換えることができます。

<Widget foo={bar} answer={42} text="hello"/>

スプレッド属性 は、多くの属性やプロパティを一度に要素やコンポーネントに渡すことを可能にします。

要素またはコンポーネントは、通常のものと混在させて、複数のスプレッド属性を持つことができます。

<Widget {...things}/>

$$props は、export で宣言されていないものも含めて、コンポーネントに渡されるすべてのプロパティ(props)を参照します。これは Svelte の最適化が難しいので、一般的には推奨されません。しかし、コンパイル時にどのようなプロパティがコンポーネントに渡されるかわからない場合など、稀なケースでは便利です。

<Widget {...$$props}/>

$$restProps には、export で宣言されて いない プロパティ(props)のみが含まれます。これは他の未知の属性をコンポーネントの要素に渡すために使用できます。 $$props と同じ最適化の問題を共有しており、同様に推奨されません。

<input {...$$restProps}>

input 要素やその子要素である option 要素の value 属性は、bind:groupbind:checked を使用している場合、スプレッド属性で設定してはいけません。このような場合、バインドされる変数にリンクできるように、Svelteがその要素のvalueをマークアップの中で直接見ることができる必要があります。

Text expressions

{expression}

テキストにもJavaScriptの式を含めることができます。

<h1>Hello {name}!</h1>
<p>{a} + {b} = {a + b}.</p>

Comments

コンポーネント内でHTMLコメントを使用することができます。

<!-- this is a comment! -->
<h1>Hello world</h1>

svelte-ignore で始まるコメントは、マークアップの次のブロックに対する警告を無効にします。通常、これらはアクセシビリティの警告です。正当な理由で警告を無効にしていることを確認してください。

<!-- svelte-ignore a11y-autofocus -->
<input bind:value={name} autofocus>

{#if ...}

{#if}...{/if}
{#if}...{:else if}...{/if}
{#if}...{:else}...{/if}

条件付きでレンダリングされるコンテンツは、if ブロックで囲むことができます。

{#if answer === 42}
	<p>what was the question?</p>
{/if}

追加の条件は {:else if 式} で付け足すことができ、{:else} 句で終わらせることもできます。

{#if porridge.temperature > 100}
	<p>too hot!</p>
{:else if 80 > porridge.temperature}
	<p>too cold!</p>
{:else}
	<p>just right!</p>
{/if}

{#each ...}

{#each as name}...{/each}
{#each as name, index}...{/each}
{#each as name (key)}...{/each}
{#each as name, index (key)}...{/each}
{#each as name}...{:else}...{/each}

each ブロックで値のリストの反復処理ができます。

<h1>Shopping list</h1>
<ul>
	{#each items as item}
		<li>{item.name} x {item.qty}</li>
	{/each}
</ul>

配列や配列のような値(つまり length プロパティを持つオブジェクト)を反復処理するのに each ブロックを使用できます。

each ブロックは array.map(...) のコールバックの第2数に相当するインデックスを指定することもできます。

{#each items as item, i}
	<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}

key の式(各リストアイテムを一意に識別できる必要があります)が与えられた場合、Svelte は、データが変化したときに(末尾にアイテムを追加したり削除するのではなく)キーを使用してリストの差分を取ります。key はどんなオブジェクトでもよいですが、そのオブジェクト自体が変更されたときに同一性を維持できるため、文字列か数値をお勧めします。

{#each items as item (item.id)}
	<li>{item.name} x {item.qty}</li>
{/each}

<!-- もしくはインデックスを追加 -->
{#each items as item, i (item.id)}
	<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}

each ブロックでは分割代入や残余構文のパターンを自由に使えます。

{#each items as { id, name, qty }, i (id)}
	<li>{i + 1}: {name} x {qty}</li>
{/each}

{#each objects as { id, ...rest }}
	<li><span>{id}</span><MyComponent {...rest}/></li>
{/each}

{#each items as [id, ...rest]}
	<li><span>{id}</span><MyComponent values={rest}/></li>
{/each}

each ブロックには {:else} 句を入れることもできます。これはリストが空の場合にレンダリングされます。

{#each todos as todo}
	<p>{todo.text}</p>
{:else}
	<p>No tasks today!</p>
{/each}

{#await ...}

{#await}...{:then name}...{:catch name}...{/await}
{#await}...{:then name}...{/await}
{#await 式 then name}...{/await}
{#await 式 catch name}...{/await}

await ブロックを使用すると、Promise が取りうる 3 つの状態(保留中、成功、失敗)に分岐できます。

{#await promise}
	<!-- promise が保留中 -->
	<p>waiting for the promise to resolve...</p>
{:then value}
	<!-- promise が成功した -->
	<p>The value is {value}</p>
{:catch error}
	<!-- promise が失敗した -->
	<p>Something went wrong: {error.message}</p>
{/await}

promise が失敗した時に何もレンダリングする必要がない場合(もしくはエラーが発生しない場合)は catch ブロックを省略できます。

{#await promise}
	<!-- promise が保留中 -->
	<p>waiting for the promise to resolve...</p>
{:then value}
	<!-- promise が成功した -->
	<p>The value is {value}</p>
{/await}

保留中の状態を気にしない場合は、最初のブロックを省略することもできます。

{#await promise then value}
	<p>The value is {value}</p>
{/await}

逆にエラー状態のみを表示したい場合は then ブロックを省略できます。

{#await promise catch error}
	<p>The error is {error}</p>
{/await}

{#key ...}

{#key 式}...{/key}

key ブロックは式の値が変更されたときに、その中身を破棄して再作成します。

これは、ある値が変更されるたびに要素のトランジションを再生したい場合に便利です。

{#key value}
	<div transition:fade>{value}</div>
{/key}

コンポーネントを囲んで使用した場合、コンポーネントの再インスタンス化と再初期化をもたらします。

{#key value}
	<Component />
{/key}

{@html ...}

{@html 式}

テキスト式({式} の構文)では、 <> のような文字はエスケープされますが、HTML 式ではエスケープされません。

式は単独で正しい HTML になっている必要があります。{@html "<div>"}content{@html "</div>"}</div> の部分が正しい HTML ではないため、動作しません。また、Svelteコードをコンパイルすることもできません。

Svelte は HTML を挿入する前に式をサニタイズしません。データが信頼できないソースからのものである場合は自分でサニタイズする必要があります。そうしないと、ユーザーを XSS の脆弱性にさらしてしまいます。

<div class="blog-post">
	<h1>{post.title}</h1>
	{@html post.content}
</div>

{@debug ...}

{@debug}
{@debug 変数1, 変数2, ..., 変数N}

{@debug ...} タグは console.log(...) の代わりになります。指定した変数の値が変更されるたびログに出力し、devtools が開いているとコードの実行を一時停止します。

<script>
	let user = {
		firstname: 'Ada',
		lastname: 'Lovelace'
	};
</script>

{@debug user}

<h1>Hello {user.firstname}!</h1>

{@debug ...} はカンマ区切りの(任意の式ではなく)変数名のリストを受け取ります。

<!-- コンパイルされる -->
{@debug user}
{@debug user1, user2, user3}

<!-- コンパイルできない -->
{@debug user.firstname}
{@debug myArray[0]}
{@debug !isReady}
{@debug typeof user === 'object'}

引数なしの {@debug} タグは、(変数を指定した場合とは逆に)状態のどれかが変化した時にトリガされる debugger 文を挿入します。

Element directives

要素には、属性と同じようにディレクティブを持たせることができます。これは何らかの方法で要素の動作を制御します。

on:eventname

on:eventname={handler}
on:eventname|modifiers={handler}

DOM イベントをリッスンするには on: ディレクティブを使用します。

<script>
	let count = 0;

	function handleClick(event) {
		count += 1;
	}
</script>

<button on:click={handleClick}>
	count: {count}
</button>

ハンドラはパフォーマンスを低下させることなくインラインで宣言できます。 属性と同様、ディレクティブの値はシンタックスハイライトのために引用符で囲むことができます。

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

| の文字を使って DOM イベントに修飾子を追加します。

<form on:submit|preventDefault={handleSubmit}>
	<!-- `submit` イベントの規定の動作が妨げられ
		 ページはリロードされません -->
</form>

次の修飾子を使用できます:

  • preventDefault — ハンドラを実行する前に event.preventDefault() を呼び出します
  • stopPropagationevent.stopPropagation() を呼び出し、イベントが次の要素に到達するのを防ぎます
  • passive — タッチ/ホイールイベントのスクロールパフォーマンスを向上させます(Svelte は追加することが安全な箇所には自動的に追加します)
  • nonpassive — 明示的に passive: false を設定します
  • captureバブリングフェーズではなくキャプチャフェーズ中にハンドラを実行します
  • once — ハンドラが最初に実行された後、削除します
  • self — event.target がその要素自体だった場合のみハンドラをトリガします

修飾子は連鎖させることができます。例 on:click|once|capture={...}

on: ディレクティブが値なしで使用された場合、コンポーネントはイベントを転送します。つまりコンポーネントの使用者がイベントをリッスンできます。

<button on:click>
	コンポーネント自体がクリックイベントを発火します
</button>

同じイベントに対して複数のイベントリスナを持つことができます。

<script>
	let counter = 0;
	function increment() {
		counter = counter + 1;
	}

	function track(event) {
		trackEvent(event)
	}
</script>

<button on:click={increment} on:click={track}>Click me!</button>

bind:property

bind:property={variable}

データは通常、親から子へと流れていきます。bind: ディレクティブにより、データを子から親へと逆方向に流すことができます。ほとんどのバインディングは個々の要素に特有です。

もっともシンプルなバインディングは、input.value のようなプロパティの値を示します。

<input bind:value={name}>
<textarea bind:value={text}></textarea>

<input type="checkbox" bind:checked={yes}>

名前が値と一致する場合は、省略形を使用できます。

<!-- These are equivalent -->
<input bind:value={value}>
<input bind:value>

数値の入力値は強制されます。つまり、DOM に関する限り input.value は文字列ですが、Svelte はそれを数値として扱います。入力が empty や 無効な値の場合 (type="number" であれば) 値は undefined になります。

<input type="number" bind:value={num}>
<input type="range" bind:value={num}>

type="file" である <input> 要素では、選択ファイルの FileList を取得するために bind:files を使用できます。これは読み取り専用です。

<label for="avatar">Upload a picture:</label>
<input
	accept="image/png, image/jpeg"
	bind:files
	id="avatar"
	name="avatar"
	type="file"
/>
Binding <select> value

<select> 値のバインディングは、選択された <option>value プロパティに対応しており、(通常の DOM のように文字列だけでなく)どんな値でも設定できます。

<select bind:value={selected}>
	<option value={a}>a</option>
	<option value={b}>b</option>
	<option value={c}>c</option>
</select>

<select multiple> 要素はチェックボックスのグループと同様の動作になります。

<select multiple bind:value={fillings}>
	<option value="Rice">Rice</option>
	<option value="Beans">Beans</option>
	<option value="Cheese">Cheese</option>
	<option value="Guac (extra)">Guac (extra)</option>
</select>

<option> の値がテキスト内容と一致する場合、value 属性は省略できます。

<select multiple bind:value={fillings}>
	<option>Rice</option>
	<option>Beans</option>
	<option>Cheese</option>
	<option>Guac (extra)</option>
</select>

contenteditable 属性を持つ要素は innerHTMLtextContent のバインディングをサポートします。

<div contenteditable="true" bind:innerHTML={html}></div>
Media element bindings

メディア要素 (<audio><video>) には、独自のバインディングのセットがあります -- 6つの readonly と…

  • duration (readonly) — 動画の総再生時間(秒単位)です。
  • buffered (readonly) — {start, end} オブジェクトの配列です。
  • played (readonly) — 同上
  • seekable (readonly) — 同上
  • seeking (readonly) — Boolean
  • ended (readonly) — Boolean

…そして5つの 双方向 バインディング。

  • currentTime — 動画の現在の再生時間、秒単位です。
  • playbackRate — どれぐらい早く、または遅く動画を再生するか、1 が '通常値' です。
  • paused — これは自明のはずです。
  • volume — 0 から 1 の間の値です。
  • muted — Booleanの値で、true はミュートになります。

動画にはさらに、videoWidthvideoHeight という読み取り専用のバインディングがあります。

<video
	src={clip}
	bind:duration
	bind:buffered
	bind:played
	bind:seekable
	bind:seeking
	bind:ended
	bind:currentTime
	bind:playbackRate
	bind:paused
	bind:volume
	bind:muted
	bind:videoWidth
	bind:videoHeight
></video>
Block-level element bindings

ブロックレベル要素は、これと同様の手法で測定された4つの読み取り専用バインディングを持っています。

  • clientWidth
  • clientHeight
  • offsetWidth
  • offsetHeight
<div
	bind:offsetWidth={width}
	bind:offsetHeight={height}
>
	<Chart {width} {height}/>
</div>

bind:group

bind:group={variable}

グループ化させたい入力にはbind:groupを使用できます。

<script>
	let tortilla = 'Plain';
	let fillings = [];
</script>

<!-- こちらのグループ化されたラジオinputは相互に排他的です -->
<input type="radio" bind:group={tortilla} value="Plain">
<input type="radio" bind:group={tortilla} value="Whole wheat">
<input type="radio" bind:group={tortilla} value="Spinach">

<!-- こちらのグループ化されたチェックボックスinputは配列にデータを挿入します -->
<input type="checkbox" bind:group={fillings} value="Rice">
<input type="checkbox" bind:group={fillings} value="Beans">
<input type="checkbox" bind:group={fillings} value="Cheese">
<input type="checkbox" bind:group={fillings} value="Guac (extra)">

bind:this

bind:this={dom_node}

DOM ノードを参照するには bind:this を使用します。

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

	let canvasElement;

	onMount(() => {
		const ctx = canvasElement.getContext('2d');
		drawStuff(ctx);
	});
</script>

<canvas bind:this={canvasElement}></canvas>

class:name

class:name={value}
class:name

class:というディレクティブは要素のクラスを切り替えるための簡単な方法を提供してくれます。

<!-- この二つは同等です -->
<div class="{active ? 'active' : ''}">...</div>
<div class:active={active}>...</div>

<!-- 名前と値が一致する場合の省略形がこちらです -->
<div class:active>...</div>

<!-- 複数のクラスの切り替えを含めることができます -->
<div class:active class:inactive={!active} class:isAdmin>...</div>

use:action

use:action
use:action={parameters}
action = (node: HTMLElement, parameters: any) => {
	update?: (parameters: any) => void,
	destroy?: () => void
}

アクションは、要素が作成されたときに呼び出される関数です。要素がアンマウントされたときに呼び出される destroy メソッドをもつオブジェクトを返すことができます。

<script>
	function foo(node) {
		// the node has been mounted in the DOM

		return {
			destroy() {
				// the node has been removed from the DOM
			}
		};
	}
</script>

<div use:foo></div>

アクションはパラメータを取ることができます。戻り値に update メソッドがあると、そのパラメータが変化するときはいつも、Svelte がマークアップに更新を適用した直後にそのメソッドが呼び出されます。

すべてのコンポーネントインスタンスに対して foo 関数を再宣言しているという事実について心配する必要はありません。Svelte は、ローカル状態に依存しない関数をコンポーネント定義から巻き上げます。

<script>
	export let bar;

	function foo(node, bar) {
		// the node has been mounted in the DOM

		return {
			update(bar) {
				// the value of `bar` has changed
			},

			destroy() {
				// the node has been removed from the DOM
			}
		};
	}
</script>

<div use:foo={bar}></div>

transition:fn

transition:fn
transition:fn={params}
transition:fn|local
transition:fn|local={params}
transition = (node: HTMLElement, params: any) => {
	delay?: number,
	duration?: number,
	easing?: (t: number) => number,
	css?: (t: number, u: number) => string,
	tick?: (t: number, u: number) => void
}

トランジションは、状態変化の結果として DOM に出入りする要素によってトリガーされます。

ブロックが外へのトランジションをしているとき、ブロック内のすべての要素(独自のトランジションを持たない要素を含む)は、ブロック内のすべてのトランジジョンが完了するまで DOM に保持されます。

transition: ディレクティブは 双方向 トランジションを示しており、トランジションが進行している間、円滑に反転させることができることを意味しています。

{#if visible}
	<div transition:fade>
		fades in and out
	</div>
{/if}

デフォルトでは、イントロトランジションは最初のレンダリングでは再生されません。この動作は、コンポーネントを作成する ときに intro: true を設定することで変更できます。

Transition parameters

アクションと同様に、トランジションはパラメータを持つことができます。

(ダブル {{中括弧}} は特殊な構文ではありません。これは式タグ内のオブジェクトリテラルです)

{#if visible}
	<div transition:fade="{{ duration: 2000 }}">
		flies in, fades out over two seconds
	</div>
{/if}
Custom transition functions

トランジションはカスタム関数を使うことができます。返されたオブジェクトに css 関数があれば、Svelte は要素上で再生される CSS アニメーションを作成します。

css に渡される t 引数は easing 関数を適用した後の 0 から 1 の間の値です。 In トランジションは 0 から 1 まで、out トランジションは 1 から 0 までの間で実行されます。-- 言い換えれば、1 はトランジションが適用されていないかのような要素の自然な状態です。 引数 u1 - t と等しくなります。

この関数はトランジションが始まる 前に 繰り返し呼び出され、異なる tu の引数を持ちます。

<script>
	import { elasticOut } from 'svelte/easing';

	export let visible;

	function whoosh(node, params) {
		const existingTransform = getComputedStyle(node).transform.replace('none', '');

		return {
			delay: params.delay || 0,
			duration: params.duration || 400,
			easing: params.easing || elasticOut,
			css: (t, u) => `transform: ${existingTransform} scale(${t})`
		};
	}
</script>

{#if visible}
	<div in:whoosh>
		whooshes in
	</div>
{/if}

カスタムのトランジション関数は tick 関数を返すこともでき、これは同じ tu の引数を持つトランジションの 最中に 呼び出されます。

tick の代わりに css を使うことが可能ならば、そうしてください。-- CSS アニメーションはメインスレッドの外で実行することができるため、遅いデバイスでのジャンクを防ぐことができます。

<script>
	export let visible = false;

	function typewriter(node, { speed = 50 }) {
		const valid = (
			node.childNodes.length === 1 &&
			node.childNodes[0].nodeType === Node.TEXT_NODE
		);

		if (!valid) return {};

		const text = node.textContent;
		const duration = text.length * speed;

		return {
			duration,
			tick: (t, u) => {
				const i = ~~(text.length * t);
				node.textContent = text.slice(0, i);
			}
		};
	}
</script>

{#if visible}
	<p in:typewriter="{{ speed: 20 }}">
		The quick brown fox jumps over the lazy dog
	</p>
{/if}

トランジションがトランジションオブジェクトではなく関数を返す場合、その関数は次のマイクロタスクで呼び出されます。これにより、複数のトランジションを調整することができ、クロスフェード効果 が可能になります。

Transition events

トランジションを持つ要素は、標準的なDOMイベントに加えて以下のイベントをディスパッチします。

  • introstart
  • introend
  • outrostart
  • outroend
{#if visible}
	<p
		transition:fly="{{ y: 200, duration: 2000 }}"
		on:introstart="{() => status = 'intro started'}"
		on:outrostart="{() => status = 'outro started'}"
		on:introend="{() => status = 'intro ended'}"
		on:outroend="{() => status = 'outro ended'}"
	>
		Flies in and out
	</p>
{/if}

ローカルトランジションは、親ブロックが作成または破棄されたときには再生されず、所属するブロックが作成または破棄されたときにのみ再生されます。

{#if x}
	{#if y}
		<p transition:fade>
			fades in and out when x or y change
		</p>

		<p transition:fade|local>
			fades in and out only when y changes
		</p>
	{/if}
{/if}

in:fn/out:fn

in:fn
in:fn={params}
in:fn|local
in:fn|local={params}
out:fn
out:fn={params}
out:fn|local
out:fn|local={params}

transition: に似ていますが、in: は DOM に入る要素だけに、out: は出る要素だけに適用されます。

transition: とは違って、in:out: を適用したトランジションは双方向ではありません。つまり、もしトランジションの最中にブロックがアウトロされた場合、逆転するのではなく、イントロトランジションはアウトロトランジションと一緒に「再生」し続けます。アウトロトランジションが中止された場合、トランジションは最初から再開されます。

{#if visible}
	<div in:fly out:fade>
		flies in, fades out
	</div>
{/if}

animate:fn

animate:name
animate:name={params}
animation = (node: HTMLElement, { from: DOMRect, to: DOMRect } , params: any) => {
	delay?: number,
	duration?: number,
	easing?: (t: number) => number,
	css?: (t: number, u: number) => string,
	tick?: (t: number, u: number) => void
}
DOMRect {
	bottom: number,
	height: number,
	​​left: number,
	right: number,
	​top: number,
	width: number,
	x: number,
	y: number
}

アニメーションは、keyed each block の内容が並び替えられたときに発生します。アニメーションは、要素が削除されたときには実行されず、each ブロックのデータが並べ替えられたときにのみ実行されます。animate ディレクティブは、キー付き each ブロックの 直接の 子要素になければいけません。

アニメーションは Svelte の組み込みアニメーション関数 または カスタムアニメーション関数 を使用することができます。

<!-- When `list` is reordered the animation will run-->
{#each list as item, index (item)}
	<li animate:flip>{item}</li>
{/each}
Animation Parameters

アクションやトランジションと同様に、アニメーションはパラメータを持つことができます。

(ダブル {{中括弧}} は特殊な構文ではありません。これは式タグ内のオブジェクトリテラルです)

{#each list as item, index (item)}
	<li animate:flip="{{ delay: 500 }}">{item}</li>
{/each}
Custom animation functions

アニメーションは、nodeanimation オブジェクト、および任意の paramaters を引数として指定するカスタム関数を使用することができます。animation パラメータは、fromto プロパティを含むオブジェクトで、それぞれ要素の startend の位置におけるジオメトリを記述した DOMRect を含みます。from プロパティは要素の開始位置の DOMRect であり、to プロパティはリストが並び替えられ DOM が更新された後の最終位置の DOMRect です。

返されたオブジェクトが css メソッドを持つ場合、Svelte は要素上で再生される CSS アニメーションを作成します。

css に渡される t 引数は easing 関数が適用された後の 01 の値です。引数 u1 - t に等しい値です。

この関数はアニメーションが始まる 前に 繰り返し呼ばれ、異なる tu の引数を持ちます。

<script>
	import { cubicOut } from 'svelte/easing';

	function whizz(node, { from, to }, params) {

		const dx = from.left - to.left;
		const dy = from.top - to.top;

		const d = Math.sqrt(dx * dx + dy * dy);

		return {
			delay: 0,
			duration: Math.sqrt(d) * 120,
			easing: cubicOut,
			css: (t, u) =>
				`transform: translate(${u * dx}px, ${u * dy}px) rotate(${t*360}deg);`
		};
	}
</script>

{#each list as item, index (item)}
	<div animate:whizz>{item}</div>
{/each}

カスタムアニメーション関数は tick 関数を返すこともできます。tick 関数はアニメーションの 最中 に呼び出され、同じ tu を引数に取ります。

tick の代わりに css を使うことが可能ならば、そうしてください。-- CSS アニメーションはメインスレッドの外で実行することができるため、遅いデバイスでのジャンクを防ぐことができます。

<script>
	import { cubicOut } from 'svelte/easing';

	function whizz(node, { from, to }, params) {

		const dx = from.left - to.left;
		const dy = from.top - to.top;

		const d = Math.sqrt(dx * dx + dy * dy);

		return {
		delay: 0,
		duration: Math.sqrt(d) * 120,
		easing: cubicOut,
		tick: (t, u) =>
			Object.assign(node.style, {
				color: t > 0.5 ? 'Pink' : 'Blue'
			});
	};
	}
</script>

{#each list as item, index (item)}
	<div animate:whizz>{item}</div>
{/each}

Component directives

on:eventname

on:eventname={handler}

コンポーネントは createEventDispatcher を用いるか、または DOM イベントをフォワードすることでイベントを発火することができます。コンポーネントのイベントをリッスンするための書き方は、DOM イベントをリッスンする書き方と同じです:

<SomeComponent on:whatever={handler}/>

DOM イベントと同様に、on: ディレクティブが値なしに使われる場合、コンポーネントはイベントをフォワードしますが、これはコンポーネントのユーザーがイベントをリッスンできることを意味します。

<SomeComponent on:whatever/>

bind:property

bind:property={variable}

要素と同じ構文を用いてコンポーネントのプロパティにバインドすることができます。

<Keypad bind:value={pin}/>

bind:this

bind:this={component_instance}

コンポーネントは bind:this もサポートしており、これを用いることでコンポーネントのインスタンスをプログラムで操作できるようになります。

ボタンが最初にレンダリングされるときには cartundefined であり、エラーを投げるので{cart.empty}を実行できないことに注意してください。

<ShoppingCart bind:this={cart}/>

<button on:click={() => cart.empty()}>
	Empty shopping cart
</button>

<slot>

<slot><!-- optional fallback --></slot>
<slot name="x"><!-- optional fallback --></slot>
<slot prop={value}></slot>

コンポーネントは要素と同じ様に、子コンテンツを持つことができます。

コンテンツは <slot> 要素を用いて子コンポーネントに公開され、子が何も提供されない場合、レンダリングされるフォールバックのコンテンツを含みます。

<!-- Widget.svelte -->
<div>
	<slot>
		this fallback content will be rendered when no content is provided, like in the first example
	</slot>
</div>

<!-- App.svelte -->
<Widget></Widget> <!-- this component will render the default content -->

<Widget>
	<p>this is some child content that will overwrite the default slot content</p>
</Widget>

<slot name="name">

名前付きスロットは、特定の場所をターゲットにすることを可能にします。 また、フォールバックのコンテンツを含むこともできます。

<!-- Widget.svelte -->
<div>
	<slot name="header">No header was provided</slot>
	<p>Some content between header and footer</p>
	<slot name="footer"></slot>
</div>

<!-- App.svelte -->
<Widget>
	<h1 slot="header">Hello</h1>
	<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</Widget>

コンポーネントは、<Component slot="name" />という構文を使って、名前付きスロットに入れることができます。 ラッパー要素を使うことなくスロットに内容を入れるために、特殊な要素<svelte:fragment>を使うことができます。

<!-- Widget.svelte -->
<div>
	<slot name="header">No header was provided</slot>
	<p>Some content between header and footer</p>
	<slot name="footer"></slot>
</div>

<!-- App.svelte -->
<Widget>
	<HeaderComponent slot="header" />
	<svelte:fragment slot="footer">
		<p>All rights reserved.</p>
		<p>Copyright (c) 2019 Svelte Industries</p>
	</svelte:fragment>
</Widget>

$$slots

$$slots は、親からコンポーネントに渡されたスロットの名前がキーとなるオブジェクトです。親が特定の名前のスロットを渡さなかった場合、その名前は $$slots には存在しません。これにより、親がスロットを指定した場合にのみコンポーネントがスロット (と他の要素、例えばスタイリング用のラッパーなど)をレンダリングすることができます。

注意してください、明示的に空の名前付きスロットを渡すと、そのスロットの名前が $$slots に追加されます。例えば、親が <div slot="title" /> を子コンポーネントに渡した場合、$$slots.title は子コンポーネント内で有効になります。

<!-- Card.svelte -->
<div>
	<slot name="title"></slot>
	{#if $$slots.description}
		<!-- この<hr>とスロットは、"description"という名前のスロットが提供されている場合にのみレンダリングされます。 -->
		<hr>
		<slot name="description"></slot>
	{/if}
</div>

<!-- App.svelte -->
<Card>
	<h1 slot="title">Blog Post Title</h1>
	<!-- "description"という名前のスロットは提供されていないので、該当しないスロットはレンダリングされません。 -->
</Card>

<slot key={value}>

スロットは0回以上レンダリングすることができ、プロパティ(props)を使って親に値を 戻す ことができます。親は let: ディレクティブを使ってスロットテンプレートに値を公開します。

通常の短縮ルールが適用されます -- let:itemlet:item={item} と同等であり、<slot {item}><slot item={item}> と同等です。

<!-- FancyList.svelte -->
<ul>
	{#each items as item}
		<li class="fancy">
			<slot prop={item}></slot>
		</li>
	{/each}
</ul>

<!-- App.svelte -->
<FancyList {items} let:prop={thing}>
	<div>{thing.text}</div>
</FancyList>

名前付きスロットは値を公開することもできます。let: ディレクティブは slot 属性を持つ要素に適用されます。

<!-- FancyList.svelte -->
<ul>
	{#each items as item}
		<li class="fancy">
			<slot name="item" {item}></slot>
		</li>
	{/each}
</ul>

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

<!-- App.svelte -->
<FancyList {items}>
	<div slot="item" let:item>{item.text}</div>
	<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</FancyList>

<svelte:self>

<svelte:self> 要素を使用すると、コンポーネントにそれ自体を再帰的に含めることができます。

マークアップのトップレベルに表示することはできません。また、無限ループを防ぐために、 ifeach ブロックの内側に入れるか、コンポーネントのスロットに渡す必要があります。

<script>
	export let count;
</script>

{#if count > 0}
	<p>counting down... {count}</p>
	<svelte:self count="{count - 1}"/>
{:else}
	<p>lift-off!</p>
{/if}

<svelte:component>

<svelte:component this={expression}/>

<svelte:component> 要素は、 this プロパティで指定されたコンポーネントのコンストラクタを用いて、コンポーネントを動的にレンダリングします。プロパティが変更されると、コンポーネントは破棄されて再生成されます。

this の値が falsy である場合、コンポーネントはレンダリングされません。

<svelte:component this={currentSelection.component} foo={bar}/>

<svelte:window>

<svelte:window on:event={handler}/>
<svelte:window bind:prop={value}/>

<svelte:window> 要素を使うと、コンポーネントが破棄されたときにイベントリスナを削除したり、サーバサイドでレンダリングするときに window が存在するかどうかをチェックしたりすることなく、window オブジェクトにイベントリスナを追加することができます。

<svelte:self>とは逆に、この要素はコンポーネントのトップレベルにのみ置くことができ、ブロックや要素の中に置くことはできません。

<script>
	function handleKeydown(event) {
		alert(`pressed the ${event.key} key`);
	}
</script>

<svelte:window on:keydown={handleKeydown}/>

また、以下のプロパティにバインドすることもできます。

  • innerWidth
  • innerHeight
  • outerWidth
  • outerHeight
  • scrollX
  • scrollY
  • online — window.navigator.onLine の別名です

scrollXscrollY 以外はすべて読み込み専用です。

<svelte:window bind:scrollY={y}/>

<svelte:body>

<svelte:body on:event={handler}/>

<svelte:window> と同様に、この要素を使うことで document.body のイベント、例えば window では発生しない mouseentermouseleave などのリスナを追加することができます。また、コンポーネントのトップレベルに表示する必要があります。

<svelte:body
	on:mouseenter={handleMouseenter}
	on:mouseleave={handleMouseleave}
/>

<svelte:head>

<svelte:head>...</svelte:head>

この要素を使うと、 document.head に要素を挿入することができます。サーバサイドのレンダリングでは、head の内容はメインの html の内容とは別に公開されます。

<svelte:window><svelte:head> と同様に、この要素はコンポーネントのトップレベルに表示する必要があり、ブロックや他の要素の中に置くことはできません。

<svelte:head>
	<link rel="stylesheet" href="tutorial/dark-theme.css">
</svelte:head>

<svelte:options>

<svelte:options option={value}/>

<svelte:options> 要素は、コンポーネントごとのコンパイラオプションを指定する場所を提供します。これらは コンパイラセクション で詳しく説明されています。使用できるオプションは以下の通りです。

  • immutable={true} — 変異可能なデータは絶対に使いません。そのため、コンパイラは値が変更されたかどうかを判断するために単純な参照等価性チェックを行うことができます。
  • immutable={false} — デフォルトです。Svelte は、変更可能なオブジェクトが変更されたかどうかについて、より保守的になります。
  • accessors={true} — コンポーネントのプロパティ(props)のゲッターとセッターを追加します。
  • accessors={false} — 初期値です
  • namespace="..." — このコンポーネントが使用される名前空間、最も一般的には "svg "です。大文字小文字を区別しない属性名とHTML固有の警告を除外するために "外部の" 名前空間を使用します。
  • tag="..." — このコンポーネントをカスタム要素としてコンパイルする際に使用する名前。
<svelte:options tag="my-custom-element"/>

<svelte:fragment>

<svelte:fragment>要素によって、コンテナとなるDOM要素でラップすることなく名前付きスロットに内容を入れることができます。

<!-- Widget.svelte -->
<div>
	<slot name="header">No header was provided</slot>
	<p>Some content between header and footer</p>
	<slot name="footer"></slot>
</div>

<!-- App.svelte -->
<Widget>
	<h1 slot="header">Hello</h1>
	<svelte:fragment slot="footer">
		<p>All rights reserved.</p>
		<p>Copyright (c) 2019 Svelte Industries</p>
	</svelte:fragment>
</Widget>

Run time

svelte

svelte パッケージは、ライフサイクル関数コンテキストAPI を公開します。

onMount

onMount(callback: () => void)
onMount(callback: () => () => void)

onMount 関数は、コンポーネントが DOM にマウントされるとすぐに実行されるコールバックをスケジュールします。これはコンポーネントの初期化中に呼び出されなければなりません (ただし、コンポーネントの 内部 に存在する必要はありません。外部モジュールから呼び出すことができます)。

onMountサーバーサイドコンポーネント の内部では実行されません。

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

	onMount(() => {
		console.log('the component has mounted');
	});
</script>

onMount から関数が返された場合、コンポーネントがアンマウントされたときに呼び出されます。

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

	onMount(() => {
		const interval = setInterval(() => {
			console.log('beep');
		}, 1000);

		return () => clearInterval(interval);
	});
</script>

この挙動は、onMount に渡された関数が 同期的に 値を返す場合にのみ動作します。async の関数は常に Promise を返すため、同期的に 値を返すことはできません。

beforeUpdate

beforeUpdate(callback: () => void)

state が変化した後、コンポーネントが更新される直前に実行されるコールバックをスケジュールします。

コールバックが最初に実行されるのは、初回の onMount の前になります。

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

	beforeUpdate(() => {
		console.log('the component is about to update');
	});
</script>

afterUpdate

afterUpdate(callback: () => void)

コンポーネントが更新された直後に実行するコールバックをスケジュールします。

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

	afterUpdate(() => {
		console.log('the component just updated');
	});
</script>

onDestroy

onDestroy(callback: () => void)

コンポーネントがアンマウントされる直前に実行するコールバックをスケジュールします。

onMount, beforeUpdate, afterUpdate, onDestroy のうち、サーバサイドコンポーネントの中で動作するのはこれだけです。

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

	onDestroy(() => {
		console.log('the component is being destroyed');
	});
</script>

tick

promise: Promise = tick()

保留中の state の変更が適用されると resolve する promise を返します。もしくは何も保留していない場合に、その次のマイクロタスクで実行されます。

<script>
	import { beforeUpdate, tick } from 'svelte';

	beforeUpdate(async () => {
		console.log('the component is about to update');
		await tick();
		console.log('the component just updated');
	});
</script>

setContext

setContext(key: any, context: any)

任意の context オブジェクトを現在のコンポーネントと指定された key に関連付けます。context は、コンポーネントの子 (スロットコンテンツを含む) が getContext で利用できるようになります。

ライフサイクル関数と同様に、これはコンポーネントの初期化時に呼ばれなければなりません。

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

	setContext('answer', 42);
</script>

context は本質的にリアクティブではありません。リアクティブな値が必要な場合は、context にストアを渡すことができます。これはリアクティブになります。

getContext

context: any = getContext(key: any)

指定された key を持つ、最も近い親コンポーネントに属する context を取得します。コンポーネントの初期化中に呼び出されなければなりません。

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

	const answer = getContext('answer');
</script>

hasContext

hasContext: boolean = hasContext(key: any)

与えられた key が親コンポーネントの context に設定されているかどうかをチェックします。コンポーネントの初期化時に呼び出されなければなりません。

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

	if (hasContext('answer')) {
		// do something
	}
</script>

createEventDispatcher

dispatch: ((name: string, detail?: any) => void) = createEventDispatcher();

コンポーネントイベント のディスパッチに使用できるイベントディスパッチャーを作成します。 イベントディスパッチャーは、 name detail の2つの引数を取る関数です。

createEventDispatcher で作成されたコンポーネントイベントは カスタムイベント を作成します。これらのイベントは、バブリング せず、event.preventDefault() でキャンセルできません。引数 detailCustomEvent.detail プロパティに対応し、任意のタイプのデータを含むことができます。

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

	const dispatch = createEventDispatcher();
</script>

<button on:click="{() => dispatch('notify', 'detail value')}">Fire Event</button>

子コンポーネントからディスパッチされたイベントは、親でリッスンできます。 イベントがディスパッチされたときに提供されたデータはすべて、イベントオブジェクトの detailプロパティで利用できます。

<script>
	function callbackFunction(event) {
		console.log(`Notify fired! Detail: ${event.detail}`)
	}
</script>

<Child on:notify="{callbackFunction}"/>

svelte/store

svelte/store モジュールは、readablewritablederived ストアを作成するための関数をエクスポートします。

コンポーネントでリアクティブな $store 構文を便利に使うために、これらの関数を使用する必要がないことを覚えておいてください。.subscribe とそのサブスクライブの解除、(オプションで).set を正しく実装したオブジェクトは有効なストアであり、その特殊な構文と Svelte に組み込まれた derived ストアの両方で機能します。

これにより、Svelte で使用するための、ほぼすべての他のリアクティブ状態を扱うライブラリをラップすることが可能になります。続いて説明する正しい実装がどのようなものか理解するために、store contract も読んでみてください。

writable

store = writable(value?: any)
store = writable(value?: any, start?: (set: (value: any) => void) => () => void)

「外部」コンポーネントから設定できる値を持つストアを作成する関数。これは、setupdate 関数を併せ持つオブジェクトを作成します。

set は、設定する値である1つの引数を受け取る関数です。ストア値が引数の値とまだ等しくない場合、ストア値は引数の値に設定されます。

update は、コールバックである1つの引数を受け取る関数です。コールバックは、既存のストア値を引数として受け取り、ストアに設定される新しい値を返します。

import { writable } from 'svelte/store';

const count = writable(0);

count.subscribe(value => {
	console.log(value);
}); // logs '0'

count.set(1); // logs '1'

count.update(n => n + 1); // logs '2'

関数が第2引数として渡された場合、サブスクライバーの数が0から1になると呼び出されます(ただし、1から2になった場合などには呼び出されません)。その関数には、ストアの値を変更する set 関数が渡されます。その関数は、サブスクライバーの数が1から0になったときに呼び出される stop 関数を返す必要があります。

import { writable } from 'svelte/store';

const count = writable(0, () => {
	console.log('got a subscriber');
	return () => console.log('no more subscribers');
});

count.set(1); // does nothing

const unsubscribe = count.subscribe(value => {
	console.log(value);
}); // logs 'got a subscriber', then '1'

unsubscribe(); // logs 'no more subscribers'

readable

store = readable(value?: any, start?: (set: (value: any) => void) => () => void)

「外側」から値を設定できないストアを作成します。第1引数はストアの初期値です。readable の第2引数は writable の第2引数と同じです。

import { readable } from 'svelte/store';

const time = readable(null, set => {
	set(new Date());

	const interval = setInterval(() => {
		set(new Date());
	}, 1000);

	return () => clearInterval(interval);
});

derived

store = derived(a, callback: (a: any) => any)
store = derived(a, callback: (a: any, set: (value: any) => void) => void | () => void, initial_value: any)
store = derived([a, ...b], callback: ([a: any, ...b: any[]]) => any)
store = derived([a, ...b], callback: ([a: any, ...b: any[]], set: (value: any) => void) => void | () => void, initial_value: any)

1つ以上の他のストアからストアを派生させます。これらの依存しているものが変化するたびに、コールバックが実行されます。

最もシンプルな例だと、derived は単一のストアを受け取り、コールバックは派生値を返します。

import { derived } from 'svelte/store';

const doubled = derived(a, $a => $a * 2);

コールバックは、第2引数に set を受け取り、しかるべき時にそれを呼び出すことで非同期に値を設定できます。

この場合、derived に第3引数として、set が初めて呼び出される前の派生ストアの初期値を渡すこともできます。

import { derived } from 'svelte/store';

const delayed = derived(a, ($a, set) => {
	setTimeout(() => set($a), 1000);
}, 'one moment...');

コールバックから関数を返すと、a)コールバックが再度実行される時や b)最後のサブスクライバーがサブスクライブを解除する時に呼び出されます。

import { derived } from 'svelte/store';

const tick = derived(frequency, ($frequency, set) => {
	const interval = setInterval(() => {
	  set(Date.now());
	}, 1000 / $frequency);

	return () => {
		clearInterval(interval);
	};
}, 'one moment...');

どちらの場合も、第1引数として、ストア1つではなく、引数の配列を渡すことができます。

import { derived } from 'svelte/store';

const summed = derived([a, b], ([$a, $b]) => $a + $b);

const delayed = derived([a, b], ([$a, $b], set) => {
	setTimeout(() => set($a + $b), 1000);
});

get

value: any = get(store)

通常は、ストアをサブスクライブして、ストア値が切り替わるたびに使用する方法で読み取るほうがよいでしょう。しかし、場合によっては、サブスクライブしていないストア値を取得する必要があります。get はそれを可能にします。

これは、サブスクリプションを作成し、値を読み取ってから、サブスクリプションを解除することで機能します。したがって、ホットコードパスではお勧めしません。

import { get } from 'svelte/store';

const value = get(store);

svelte/motion

svelte/motion モジュールは、tweenedspring という2つの関数をエクスポートします。これは書き込み可能なストアを作成するためのもので、値がすぐにではなく、setupdate の後に時間の経過とともに変化するものです。

tweened

store = tweened(value: any, options)

トゥイーンされたストアは、一定の期間にわたって値を更新します。以下のオプションが利用可能です。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • duration (number, default 400) — トゥイーンの持続時間のミリ秒
  • easing (function, default t => t) — イージング関数
  • interpolate (function) — 下記を参照してください。

store.setstore.update は、インスタンス化時に渡されたオプションを上書きする第2引数 options を受け取ることができます。

どちらの関数も、トゥイーンが完了すると resolve する promise を返します。トゥイーンが中断されると、promise は resolve されません。

Svelte は2つの数値、2つの配列、または2つのオブジェクトの間を補間します(配列とオブジェクトが同じ '形状' であり、それらの '子孫' プロパティも数値である限り)。

<script>
	import { tweened } from 'svelte/motion';
	import { cubicOut } from 'svelte/easing';

	const size = tweened(1, {
		duration: 300,
		easing: cubicOut
	});

	function handleClick() {
		// これは size.update(n => n + 1) と等価です
		$size += 1;
	}
</script>

<button
	on:click={handleClick}
	style="transform: scale({$size}); transform-origin: 0 0"
>embiggen</button>

初期値が undefined または null の場合、最初の値の変更はすぐに有効になります。これは、プロパティをベースにしたトゥイーン値を設定していて、コンポーネントの最初のレンダリング時にモーションをかけたくない場合に便利です。

const size = tweened(undefined, {
	duration: 300,
	easing: cubicOut
});

$: $size = big ? 100 : 10;

interpolate オプションを指定すると、任意の 値の間でトゥイーンを行うことができます。関数 (a, b) => t => value で、a は開始値、b は目標値、t は 0 から 1 の間の数値、value は結果です。例えば、d3-interpolate パッケージを使えば、2つの色の間をスムーズに補間することができます。

<script>
	import { interpolateLab } from 'd3-interpolate';
	import { tweened } from 'svelte/motion';

	const colors = [
		'rgb(255, 62, 0)',
		'rgb(64, 179, 255)',
		'rgb(103, 103, 120)'
	];

	const color = tweened(colors[0], {
		duration: 800,
		interpolate: interpolateLab
	});
</script>

{#each colors as c}
	<button
		style="background-color: {c}; color: white; border: none;"
		on:click="{e => color.set(c)}"
	>{c}</button>
{/each}

<h1 style="color: {$color}">{$color}</h1>

spring

store = spring(value: any, options)

spring ストアは、stiffnessdamping パラメータに基づいて目標値まで徐々に変化します。tweened ストアが一定のタイミングで値を変化させるのに対し、spring ストアは既存の速度によって決定されるタイミングで変化するため、多くの状況でより自然に見える動きを可能にします。以下のオプションが利用可能です。

  • stiffness (number, default 0.15) — 0 から 1 の間の値で、高い方が「よりタイトな」スプリングを意味します。
  • damping (number, default 0.8) — 0 から 1 の間の値で、少ない方が「より弾力のある」スプリングを意味します。
  • precision (number, default 0.001) — は、スプリングが「止まった」とみなされる閾値を決定します。少ない方がより精密であることを意味します。

tweened ストアと同様に、setupdate はスプリングが止まれば resolve する promise を返します。store.stiffnessstore.damping プロパティはスプリングが動いている間に変更することができ、すぐに効果を発揮します。

setupdate はどちらも第2引数として hard または soft プロパティを持つオブジェクトを取ることができます。{ hard: true } は対象の値を即座に設定します。{ soft: n } は既存の運動量を n 秒間保持してから止まります。{ soft: true }{ soft: 0.5 } と同等です。

スプリングチュートリアルの例を参照してください。

<script>
	import { spring } from 'svelte/motion';

	const coords = spring({ x: 50, y: 50 }, {
		stiffness: 0.1,
		damping: 0.25
	});
</script>

初期値が undefined または null の場合、最初の値の変更は tweened の場合と同様に即座に有効になります (上記を参照)。

const size = spring();
$: $size = big ? 100 : 10;

svelte/transition

svelte/transition モジュールは7つの関数をエクスポートします。fadeblurflyslidescaledrawcrossfade の7つの関数をエクスポートします。これらは Svelte transitions で使用します。

fade

transition:fade={params}
in:fade={params}
out:fade={params}

要素の opacity を、in トランジションでは 0 から現在の opacity まで、out トランジションでは現在の opacity から 0 までアニメーションします。

fade は以下のパラメータを受け付けます。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • duration (number, default 400) — トランジションの持続時間のミリ秒
  • easing (function, default linear) — イージング関数

トランジション チュートリアルfade トランジションの動作を見ることができます。

<script>
	import { fade } from 'svelte/transition';
</script>

{#if condition}
	<div transition:fade="{{delay: 250, duration: 300}}">
		fades in and out
	</div>
{/if}

blur

transition:blur={params}
in:blur={params}
out:blur={params}

要素の opacity で blur フィルタをアニメーション化します。

blur は以下のパラメータを受け付けます。

  • delay (number, default 0) —開始前の待ち時間のミリ秒
  • duration (number, default 400) — アニメーションの持続時間のミリ秒
  • easing (function, default cubicInOut) — イージング関数
  • opacity (number, default 0) - アニメーション化する opacity の値
  • amount (number, default 5) - ぼかしのサイズをピクセル単位で表します
<script>
	import { blur } from 'svelte/transition';
</script>

{#if condition}
	<div transition:blur="{{amount: 10}}">
		fades in and out
	</div>
{/if}

fly

transition:fly={params}
in:fly={params}
out:fly={params}

要素の x と y の位置と opacity をアニメーション化します。in トランジションは、要素の現在の(デフォルトの)値からパラメータとして渡された値にアニメーションします。out トランジションは、指定された値から要素のデフォルト値にアニメーションします。

fly は以下のパラメータを受け付けます。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • duration (number, default 400) — トランジションの持続時間のミリ秒
  • easing (function, default cubicOut) — イージング関数
  • x (number, default 0) - アニメーションで移動する x 位置のオフセット
  • y (number, default 0) - アニメーションで移動する y 位置のオフセット
  • opacity (number, default 0) - アニメーションで変化する opacity のオフセット

fly トランジションの動作は トランジション チュートリアル で見ることができます。

<script>
	import { fly } from 'svelte/transition';
	import { quintOut } from 'svelte/easing';
</script>

{#if condition}
	<div transition:fly="{{delay: 250, duration: 300, x: 100, y: 500, opacity: 0.5, easing: quintOut}}">
		flies in and out
	</div>
{/if}

slide

transition:slide={params}
in:slide={params}
out:slide={params}

要素をスライドさせて出し入れします。

slide は下記のパラメータを受け付けます。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • duration (number, default 400) — トランジションの持続時間のミリ秒
  • easing (function, default cubicOut) — イージング関数
<script>
	import { slide } from 'svelte/transition';
	import { quintOut } from 'svelte/easing';
</script>

{#if condition}
	<div transition:slide="{{delay: 250, duration: 300, easing: quintOut }}">
		slides in and out
	</div>
{/if}

scale

transition:scale={params}
in:scale={params}
out:scale={params}

要素の opacity と scale をアニメーション化します。in トランジションは、要素の現在の(デフォルトの)値からパラメータとして渡された値にアニメーションします。out トランジションは、指定された値から要素のデフォルト値にアニメーションします。

scale は以下のパラメータを受け付けます。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • duration (number, default 400) — トランジションの持続時間のミリ秒
  • easing (function, default cubicOut) — イージング関数
  • start (number, default 0) - アニメーションで変化する scale の値
  • opacity (number, default 0) - アニメーションで変化する opacity の値
<script>
	import { scale } from 'svelte/transition';
	import { quintOut } from 'svelte/easing';
</script>

{#if condition}
	<div transition:scale="{{duration: 500, delay: 500, opacity: 0.5, start: 0.5, easing: quintOut}}">
		scales in and out
	</div>
{/if}

draw

transition:draw={params}
in:draw={params}
out:draw={params}

SVG 要素のストロークを蛇が管の中を進むようにアニメーション化します。in トランジションはパスが見えない状態から始まり、時間の経過とともにパスが画面に描画されます。out トランジションはパスが見える状態から始まり、徐々にパスを消していきます。draw<path><polyline> のように getTotalLength メソッドを持つ要素でのみ動作します。

draw は以下のパラメータを受け付けます。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • speed (number, default undefined) - アニメーションの速度、下記を参照してください
  • duration (number | function, default 800) — トランジションの持続時間のミリ秒
  • easing (function, default cubicInOut) — イージング関数

速度パラメータ speed はパスの長さに対する遷移の持続時間を設定する手段です。これはパスの長さに適用される修飾子で duration = length / speed となります。1000ピクセルで速度が1のパスの持続時間は 1000ms であり、速度を 0.5 に設定すると持続時間は2倍になり、2 に設定すると半分になります。

<script>
	import { draw } from 'svelte/transition';
	import { quintOut } from 'svelte/easing';
</script>

<svg viewBox="0 0 5 5" xmlns="http://www.w3.org/2000/svg">
	{#if condition}
		<path transition:draw="{{duration: 5000, delay: 500, easing: quintOut}}"
					d="M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z"
					fill="none"
					stroke="cornflowerblue"
					stroke-width="0.1px"
					stroke-linejoin="round"
		/>
	{/if}
</svg>

svelte/animate

svelte/animate モジュールは、Svelte animations で使用するための関数を1つエクスポートします。

flip

animate:flip={params}

flip 関数は要素の開始位置と終了位置を計算し、その間で xy の値を変換してアニメーションを行います。flipFirst, Last, Invert, Play の略です。

flip は以下のパラメータを受け付けます。

  • delay (number, default 0) — 開始前の待ち時間のミリ秒
  • duration (number | function, default d => Math.sqrt(d) * 120) — 下記を参照してください
  • easing (function, default cubicOut) — イージング関数

duration は、以下のいずれかを指定することができます。

  • number はミリ秒単位です。
  • 関数 distance: number => duration: number は、要素の移動距離をピクセル単位で受け取り、ミリ秒単位で返します。これにより、各要素の持続時間に対する移動距離を割り当てることができます。

アニメーションのチュートリアル で全ての例を見ることができます。

<script>
	import { flip } from 'svelte/animate';
	import { quintOut } from 'svelte/easing';

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

{#each list as n (n)}
	<div animate:flip="{{delay: 250, duration: 250, easing: quintOut}}">
		{n}
	</div>
{/each}

svelte/easing

イージング関数は、時間の経過とともに変化する速度を指定するもので、Svelte に組み込まれたトランジションやアニメーション、tweened や spring ユーティリティの作業をする際に便利です。svelte/easing には、31の名前付きエクスポートが含まれています。linear イージング、10種類のイージング関数の3つのバリエーション in, out, inOut です。

examples sectionease visualiser で様々なイージングを試してみることができます。

ease in out inOut
back backIn backOut backInOut
bounce bounceIn bounceOut bounceInOut
circ circIn circOut circInOut
cubic cubicIn cubicOut cubicInOut
elastic elasticIn elasticOut elasticInOut
expo expoIn expoOut expoInOut
quad quadIn quadOut quadInOut
quart quartIn quartOut quartInOut
quint quintIn quintOut quintInOut
sine sineIn sineOut sineInOut

svelte/register

Svelteコンポーネントをビルドせずに Node.js でレンダリングするには、require('svelte/register')を使います。その後 require を使って .svelte ファイルをインクルードすることができます。

require('svelte/register');

const App = require('./App.svelte').default;

...

const { html, css, head } = App.render({ answer: 42 });

.defaultは、ネイティブの JavaScript モジュールから Node が認識する CommonJS モジュールに変換するために必要です。コンポーネントが JavaScript モジュールをインポートすると、Node での読み込みに失敗するので、代わりにバンドラを使う必要があることに注意してください。

コンパイルオプションを設定したり、カスタムファイルの拡張子を使用したりするには、register フックを関数として呼び出します。

require('svelte/register')({
  extensions: ['.customextension'], // defaults to ['.html', '.svelte']
	preserveComments: true
});

Client-side component API

Creating a component

const component = new Component(options)

クライアントサイドのコンポーネント、つまり generate: 'dom'(もしくは generate オプションを指定しないまま)でコンパイルされたコンポーネントは JavaScript のクラスです。

import App from './App.svelte';

const app = new App({
	target: document.body,
	props: {
		// App.svelte に `export let answer` のようなものが
		// 含まれていると仮定:
		answer: 42
	}
});

以下の初期化オプションを与えることができます。

オプション デフォルト 説明
target none レンダリング先の HTMLElement。このオプションは必須です
anchor null target の子要素。これのすぐ前にコンポーネントがレンダリングされます
props {} コンポーネントに渡すプロパティのオブジェクト
context new Map() コンポーネントに提供するルートレベルのコンテキストのキーと値のペアの Map
hydrate false 下記参照
intro false true なら、その後の状態変化を待つのではなく、初回レンダリング時にトランジションを再生します。

target の既存の子要素はそのまま残されます。

hydrate オプションは、新しい要素を作成するのではなく、既存の DOM を(大抵はサーバーサイドレンダリングから)アップグレードするよう Svelte に指示します。これはコンポーネントが hydratable: true のオプション でコンパイルされた場合にのみ機能します。<head> 要素のハイドレーションは、サーバーサイドレンダリングのコードも hydratable: true を使ってコンパイルされた場合にのみ適切に動作します。これは head 内の各要素にマーカーを追加して、コンポーネントがハイドレーション中にどの要素を除去すべきかを認識できるようにします。

通常、target の子要素はそのまま残されますが、hydrate: true ではすべての子要素が削除されます。そのため anchor オプションは hydrate: true と一緒に使用できません。

既存の DOM はコンポーネントと一致している必要はありません。Svelte は DOM をそのまま「修復」します。

import App from './App.svelte';

const app = new App({
	target: document.querySelector('#server-rendered-html'),
	hydrate: true
});

$set

component.$set(props)

プログラムでインスタンスにプロパティ(props)をセットします。component.$set({ x: 1 }) はコンポーネントの <script> ブロック内の x = 1 と同じです。

このメソッドを呼ぶと次のマイクロタスクに更新がスケジュールされます。DOM は同期的に更新されません

component.$set({ answer: 42 });

$on

component.$on(event, callback)

コンポーネントが event をディスパッチするたびに、callback 関数が呼び出されるようにします。

呼び出されたときにイベントリスナーを削除する関数が返されます。

const off = app.$on('selected', event => {
	console.log(event.detail.selection);
});

off();

$destroy

component.$destroy()

DOM からコンポーネントを削除し、すべての onDestroy ハンドラをトリガします。

Component props

component.prop
component.prop = value

コンポーネントが accessors: true でコンパイルされている場合、各インスタンスはコンポーネントの各プロパティ(props)に対するゲッターとセッターを持ちます。値をセットすると(component.$set(...) によって起こるデフォルトの非同期更新ではなく)、同期的な更新が起こります。

カスタム要素としてコンパイルする場合を除き、デフォルトでは accessorsfalse です。

console.log(app.count);
app.count += 1;

Custom element API

Svelte コンポーネントは、customElement: true コンパイラオプションを使ってカスタム要素 (別名Webコンポーネント) にコンパイルすることもできます。コンポーネントのタグ名は <svelte:options> element で指定する必要があります。

<svelte:options tag="my-element" />

<script>
	export let name = 'world';
</script>

<h1>Hello {name}!</h1>
<slot></slot>

あるいは、tag={null} を使って、カスタム要素の利用者がそれに名前を付けるべきであることを示します。

import MyElement from './MyElement.svelte';

customElements.define('my-element', MyElement);

一度カスタム要素が定義されると、それを通常の DOM 要素として使用することができます。

document.body.innerHTML = `
	<my-element>
		<p>This is some slotted content</p>
	</my-element>
`;

デフォルトでは、カスタム要素は accessors: true でコンパイルされます。これは、任意の プロパティ が DOM 要素のプロパティとして公開されることを意味します (また、可能であれば属性として読み書き可能です)。

これを防ぐには、<svelte:options>accessors={false} を追加します。

const el = document.querySelector('my-element');

// get the current value of the 'name' prop
console.log(el.name);

// set a new value, updating the shadow DOM
el.name = 'everybody';

カスタム要素は、非Svelteアプリで利用するためのコンポーネントをパッケージ化するのに便利な方法です。それらは純粋な HTML と JavaScript の同様に、ほとんどのフレームワーク でも動作します。しかし、注意すべき重要な違いがいくつかあります。

  • スタイルは単なる scoped ではなく encapsulated(カプセル化) です。これは、:global(...) 修飾子を持つスタイルを含む、コンポーネントにはないスタイル (global.css ファイルにあるような) はカスタム要素には適用されないことを意味します。
  • スタイルは、別の .css ファイルとして抽出されるのではなく、JavaScript の文字列としてコンポーネントにインライン化されます。
  • JavaScript が読み込まれるまでシャドウ DOM は見えないので、カスタム要素は一般的にサーバーサイドのレンダリングには適していません。
  • Svelte では、スロットコンテンツは 遅延して レンダリングされます。DOMでは 先行して レンダリングします。言い換えれば、コンポーネントの <slot> 要素が {#if ...} ブロックの中にあっても、常に作成されます。同様に、{#each ...} ブロックの中に <slot> 要素を含めても、スロットの内容が何度もレンダリングされることはありません。
  • let: ディレクティブは何の効果もありません。
  • 古いブラウザをサポートするにはポリフィルが必要です。

Server-side component API

const result = Component.render(...)

クライアント側のコンポーネントとは異なり、サーバー側のコンポーネントはレンダリングしてもライフサイクルがありません。-- それらは HTML と CSS を作成するのが仕事です。そのため API が多少異なります。

サーバーサイドコンポーネントは任意のプロパティ(props)と一緒に呼びだせる render メソッドを公開しています。これは headhtmlcss プロパティを持つオブジェクトを返します。この head は見つけた <svelte:head> 要素の内容を含みます。

Svelte コンポーネントを直接 Node にインポートするには、svelte/register を使ってください。

require('svelte/register');

const App = require('./App.svelte').default;

const { head, html, css } = App.render({
	answer: 42
});

.render() メソッドは以下のパラメータを受け付けます:

パラメータ デフォルト 説明
props {} コンポーネントに渡すプロパティのオブジェクト
options {} オプションのオブジェクト

options オブジェクトは、以下のオプションを取ります:

オプション デフォルト 説明
context new Map() コンポーネントに提供するルートレベルのコンテキストのキーと値のペアの Map
const { head, html, css } = App.render(
	// props
	{ answer: 42 },
	// options
	{
		context: new Map([['context-key', 'context-value']])
	}
);

Compile time

通常、Svelte コンパイラと直接やりとりすることはなく、代わりにバンドルプラグインを使ってビルドシステムに統合することになります。

とはいえ、バンドルプラグインは一般的にコンパイラのオプションを公開しているので、コンパイラの使い方を理解しておくと便利です。

svelte.compile

result: {
	js,
	css,
	ast,
	warnings,
	vars,
	stats
} = svelte.compile(source: string, options?: {...})

ここでマジックが起こります。svelte.compile はコンポーネントのソースコードを受け取ります。そしてそれを使用して、クラスをエクスポートするJavaScriptモジュールに変えます。

const svelte = require('svelte/compiler');

const result = svelte.compile(source, {
	// options
});

以下のオプションをコンパイラに渡すことができます。どれも必須ではありません。

option default description
filename null デバッグのヒントやソースマップに使われる string です。バンドルプラグインが自動的に設定します。
name "Component" 結果として得られるJavaScriptクラスの名前を設定する string です (ただし、スコープ内の他の変数と競合する場合はコンパイラが名前を変更します)、通常は filename から推測されます。
format "esm" "esm" の場合、JavaScriptモジュールを作成します (importexport を指定します)、"cjs" の場合、CommonJSモジュールを作成します(requiremodule.exports を指定します)、これは、いくつかのサーバーサイドのレンダリング状況やテストに便利です。
generate "dom" "dom" の場合、SvelteはDOMにマウントするためのJavaScriptクラスを生成します。"ssr"の場合、サーバサイドのレンダリングに適した render メソッドを持つオブジェクトを出力します。false の場合、JavaScriptやCSSは返されず、メタデータだけが返されます。
dev false true の場合、コンポーネントに特別なコードを追加します。これは、ランタイムチェックを実行し、開発中にデバッグ情報を提供するためのものです。
immutable false true の場合、オブジェクトを変更させないことをコンパイラに伝えます。これにより、値が変更されたかどうかのチェックをより控えめにすることができます。
hydratable false true を指定すると、DOMコードを生成する際に hydrate: true ランタイムオプションが有効になり、新しいDOMをゼロから生成するのではなく、既存のDOMをアップグレードすることができます。これにより、SSRコードを生成する際に <head> 要素にマーカーが追加され、ハイドレーションがどれを置き換えるべきかを知ることができるようになります。
legacy false true ならば、element.dataset のようなものをサポートしていないIE9とIE10で動作するコードを生成します。
accessors false true の場合、ゲッターとセッターはコンポーネントのプロパティ(props)に対して作成されます。false の場合、それらは読み書きされた値に対してのみ作成されます。 (つまりconst, class, function で宣言されたもの) customElement: true でコンパイルした場合、このオプションのデフォルトは true です。
customElement false true ならば、コンパイラに通常のSvelteコンポーネントの代わりにカスタム要素のコンストラクタを生成するように指示します。
tag null Svelteにカスタム要素を登録するタグ名を指定する string。文字列は小文字の英数字で、少なくとも1つのハイフンを含んだ文字列でなければなりません。例えば "my-element".
css true true の場合、スタイルはJavaScriptクラスに含まれ、実行時に注入されます。これを false に設定して静的に生成されたCSSを使うと、JavaScriptのバンドルが小さくなり、パフォーマンスが向上するのでおすすめです。
cssHash 右記 { hash, css, name, filename }を引数に取り、スコープ付きCSSのクラス名として使われる文字列を返す関数。デフォルトでは、svelte-${hash(css)}を返します。
loopGuardTimeout 0 loopGuardTimeout msを超えてスレッドがブロックされた場合にループを解除するようにSvelteに指示する 数値 です。これは無限ループを防ぐのに便利です。利用可能なのは dev: true の場合のみです
preserveComments false true の場合、サーバサイドでのレンダリング中に HTML コメントが保存されます。デフォルトではコメントは削除されます。
preserveWhitespace false true の場合、要素内や要素間の空白は、可能であれば削除されたり単一の空白になったりするのではなく、入力したとおりに保持されます。
outputFilename null JavaScriptのソースマップに使われる 文字列 です。
cssOutputFilename null CSSのソースマップに使われる 文字列 です。
sveltePath "svelte" svelte パッケージの場所。svelte または svelte/[module] からのインポートは、それに応じて変更されます。
namespace "html" 要素の名前空間。例えば、"mathml", "svg", "foreign"

返ってきた result オブジェクトには、有用なメタデータとともにコンポーネントのコードが含まれます。

const {
	js,
	css,
	ast,
	warnings,
	vars,
	stats
} = svelte.compile(source);
  • jscss は以下のプロパティを持つオブジェクトです。
    • code は JavaScript の文字列です。
    • map はソースマップに toString()toUrl() の便利なメソッドを追加したものです。
  • ast はコンポーネントの構造を表す抽象構文ツリーです。
  • warnings はコンパイル時に生成された警告オブジェクトの配列です。各警告にはいくつかのプロパティがあります。
    • code は警告のカテゴリを識別する文字列です。
    • message は人間が読みやすい言葉で問題を説明したものです。
    • start and end はもしも警告が特定の場所に関連している場合には line, column, character プロパティを持つオブジェクトです。
    • frame は該当する場合に問題のあるコードを行番号で強調表示する文字列です。
  • vars はコンポーネントの宣言の配列です、例えば eslint-plugin-svelte3 で使用されているように、各変数はいくつかのプロパティを持っています。
    • name はそのままの意味です
    • export_name は、エクスポートされた場合に使用される名前です。 (export...as でない限り、name と一致します)
    • injectedtrue なのは、宣言はあなたが書いたコードではなく、Svelteによって注入されている場合です。
    • moduletrue なのは、モジュールの値が context="module"スクリプトで宣言されている場合です。
    • mutatedtrue なのは、値のプロパティがコンポーネント内部に割り当てられている場合です。
    • reassignedtrue なのは、コンポーネント内で値が再割り当てされている場合です。
    • referencedtrue なのは、テンプレート内で値が使われている場合です。
    • referenced_from_scripttrue なのは、宣言外の <script> の中で値が使われている場合です。
    • writabletrue なのは、値が let または var で宣言されている場合です。 (ただしconst, classfunction は除きます)
  • stats はSvelte開発チームがコンパイラを診断するために使用するオブジェクトです。これに依存してはいけません!

svelte.parse

ast: object = svelte.parse(
	source: string,
	options?: {
		filename?: string,
		customElement?: boolean
	}
)

parse 関数はコンポーネントを解析し、その抽象構文木のみを返します。generate: false オプションを指定してコンパイルするのとは異なり、これはコンポーネントを解析する以外の検証やその他の解析を行いません。

const svelte = require('svelte/compiler');

const ast = svelte.parse(source, { filename: 'App.svelte' });

svelte.preprocess

Svelte を TypeScript, PostCSS, SCSS, Less などのツールで利用できるようにするための コミュニティが管理するプリプロセッサプラグイン が多数用意されています。

svelte.preprocess APIを使って独自のプリプロセッサを書くことができます。

result: {
	code: string,
	dependencies: Array<string>
} = await svelte.preprocess(
	source: string,
	preprocessors: Array<{
		markup?: (input: { content: string, filename: string }) => Promise<{
			code: string,
			dependencies?: Array<string>
		}>,
		script?: (input: { content: string, markup: string, attributes: Record<string, string>, filename: string }) => Promise<{
			code: string,
			dependencies?: Array<string>
		}>,
		style?: (input: { content: string, markup: string, attributes: Record<string, string>, filename: string }) => Promise<{
			code: string,
			dependencies?: Array<string>
		}>
	}>,
	options?: {
		filename?: string
	}
)

preprocess 関数は、コンポーネントのソースコードを任意に変換するための便利なフックを提供します。例えば、<style lang="sass"> ブロックを純粋なCSSに変換するために使うことができます。

最初の引数はコンポーネントのソースコードです。2番目の引数は、プリプロセッサ の配列です (1つしかない場合は単独のプリプロセッサになります)。このプリプロセッサは markup, script, style 関数を持つオブジェクトであり、これらは全てオプションです。

markup, script, style 関数は、変換されたソースコードを表す code プロパティと、任意で dependencies の配列を含んだオブジェクト (またはオブジェクトを resolve する promise) を返さなければなりません。

markup 関数は、コンポーネントのソーステキスト全体と、第3引数にコンポーネントの filename が指定されている場合はそのコンポーネントの filename を受け取ります。

プリプロセッサ関数は、codedependencies に加えて map オブジェクトを返すことがあります。この map は変換を表すソースマップです。現在のバージョンのSvelteでは無視されますが、将来のバージョンのSvelteでは、プリプロセッサのソースマップを考慮に入れるかもしれません。

const svelte = require('svelte/compiler');

const { code } = await svelte.preprocess(source, {
	markup: ({ content, filename }) => {
		return {
			code: content.replace(/foo/g, 'bar')
		};
	}
}, {
	filename: 'App.svelte'
});

script関数とstyle関数はそれぞれ <script><style> 要素の内容(content)とコンポーネントのソーステキスト全体(markup)を受け取ります。これらの関数は filename に加えて要素の属性のオブジェクトを取得します。

依存関係の配列が返された場合、それが結果オブジェクトに含まれます。これは(例えば)rollup-plugin-svelte のようなパッケージで、<style> タグに @import がある場合などに、追加ファイルの変更を監視するために使われます。

const svelte = require('svelte/compiler');
const sass = require('node-sass');
const { dirname } = require('path');

const { code, dependencies } = await svelte.preprocess(source, {
	style: async ({ content, attributes, filename }) => {
		// only process <style lang="sass">
		if (attributes.lang !== 'sass') return;

		const { css, stats } = await new Promise((resolve, reject) => sass.render({
			file: filename,
			data: content,
			includePaths: [
				dirname(filename),
			],
		}, (err, result) => {
			if (err) reject(err);
			else resolve(result);
		}));

		return {
			code: css.toString(),
			dependencies: stats.includedFiles
		};
	}
}, {
	filename: 'App.svelte'
});

複数のプリプロセッサを併用することができます。最初のプリプロセッサの出力は、2番目のプリプロセッサへの入力になります。最初に markup 関数が実行され、次に scriptstyle が実行されます。

const svelte = require('svelte/compiler');

const { code } = await svelte.preprocess(source, [
	{
		markup: () => {
			console.log('this runs first');
		},
		script: () => {
			console.log('this runs third');
		},
		style: () => {
			console.log('this runs fifth');
		}
	},
	{
		markup: () => {
			console.log('this runs second');
		},
		script: () => {
			console.log('this runs fourth');
		},
		style: () => {
			console.log('this runs sixth');
		}
	}
], {
	filename: 'App.svelte'
});

svelte.walk

walk(ast: Node, {
	enter(node: Node, parent: Node, prop: string, index: number)?: void,
	leave(node: Node, parent: Node, prop: string, index: number)?: void
})

walk 関数はパーサーによって生成された抽象構文木をウォークする方法を提供します。 コンパイラの組み込みインスタンスであるestree-walkerを使用します。

ウォーカーは歩くための抽象構文木と、オプションの2つのメソッド enterleave を持つオブジェクトを受け取ります。各ノードに対して、(存在すれば) enter が呼び出されます。そして enter を実行している間に this.skip() が呼ばれない限り、各子プロセスを巡回した後、ノード上で leave が呼ばれます。

const svelte = require('svelte/compiler');
svelte.walk(ast, {
	enter(node, parent, prop, index) {
		do_something(node);
		if (should_skip_children(node)) {
			this.skip();
		}
	},
	leave(node, parent, prop, index) {
		do_something_else(node);
	}
});

svelte.VERSION

package.json で設定されている現在のバージョンです。

const svelte = require('svelte/compiler');
console.log(`running svelte version ${svelte.VERSION}`);