eyecatch

Svelte Playground からプロジェクトを作成する

Posted on 2025/12/02
# Technology

Svelte Playgroundについて

Svelte Playground とは公式サイトにある Web上でのSvelte実行環境です。
Svelteコードから JS output, CSS output, AST output などが閲覧可能で、デバッグ等が楽に行えます。
また GitHubアカウントと連携することで、自分のAppを保存でき、バグの報告やコードの共有によく使われてます。

Svelteの Tutorial的なのもやAPIなどもあり、ちょっとした Svelte の動作を確認するのに大活躍です。

https://svelte.dev/playground/hello-world

sv CLI について

sv とは Svelte Application を管理するのに便利な CLI ツールです。 npx sv create [options] [path] でアプリケーションを作成するのに使います。
sv add , sv check , sv migrate など他にもコマンドがあり、結構便利です。

https://svelte.dev/docs/cli/overview

--from-playground が追加されました

sv create --from-playground <url> で Playground の App を元に新規で作成できるようになりました。
以前遊びで作った自分のプロジェクトを元に新規で作成してみます。

Playgroundの URL は https://svelte.dev/playground/ab996f113bd4418db6a2aa3c1721559b?version=5.45.3

コマンドは sv create --from-playground="https://svelte.dev/playground/ab996f113bd4418db6a2aa3c1721559b?version=5.45.3" です。

アプリケーション作成時にはいろんな Add-ons を選択できるので結構便利ですね。
よく eslint, prettier, paraglide など選択して自動で入れてもらってます。

src 以下にこのように作成されました。

$ tree src
src
├── app.d.ts
├── app.html
├── lib
│   ├── PlaygroundLayout.svelte
│   ├── assets
│   │   └── favicon.svg
│   ├── index.ts
│   └── playground
│       └── App.svelte
└── routes
    ├── +layout.svelte
    └── +page.svelte

<!-- src/lib/playground/App.svelte -->
<script>
	let name = $state('world');
	let count = $state(0);
</script>

<div>
	<label>content
	      <textarea class='content' rows={5}></textarea>
        </label>
</div>

<div>
	<label>
		fixed
		<textarea class='fix' rows={5}></textarea>
	</label>
</div>

<style>
	textarea {
		min-width: 300px;
		max-width: 500px;
		min-height: 56px;
		max-height: 200px
	}
	.content {
		field-sizing: content;
	}
	.fix {
		field-sizing: fixed;
	}
</style>

<!-- src/lib/PlaygroundLayout.svelte -->
<script lang="ts">
	import favicon from '$lib/assets/favicon.svg';

	let { children } = $props();
	const title = 'Textarea field sizing';
	const href = 'https://svelte.dev/playground/2e0d08b760c140bcaae4fedc6499df77?version=5.45.3';
	let prefersDark = $state(true);
	let isDark = $state(true);

	function switchTheme() {
		const value = isDark ? 'light' : 'dark';

		isDark = value === 'dark';
		localStorage.setItem('sv:theme', isDark === prefersDark ? 'system' : value);
	}

	$effect(() => {
		document.documentElement.classList.remove('light', 'dark');
		prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

		const theme = localStorage.getItem('sv:theme');

		isDark = !theme ? prefersDark : theme === 'dark' || (theme === 'system' && prefersDark);
		document.documentElement.classList.add(isDark ? 'dark' : 'light');
	});
</script>

<svelte:head>
	<title>--from-playground {title}</title>
	<script>
		{
			const theme = localStorage.getItem('sv:theme');

			document.documentElement.classList.add(
				!theme || theme === 'system'
					? window.matchMedia('(prefers-color-scheme: dark)').matches
						? 'dark'
						: 'light'
					: theme
			);
		}
	</script>
</svelte:head>

<div class="layout">
	<nav class="navbar">
		<div class="nav-left">
			<a href="/" class="svelte-icon">
				<img src={favicon} alt="Svelte" width="32" height="32" />
			</a>
			<p class="title">{title}</p>
		</div>
		<div class="nav-right">
			<a {href} class="raised" target="_blank" rel="noopener noreferrer">
				--to-playground
				<span aria-hidden="true" style="margin-left:0.25em;"></span>
			</a>
			<button class="raised theme-toggle" onclick={switchTheme} aria-label="Toggle theme">
				<span class="icon"></span>
			</button>
		</div>
	</nav>

	<main class="content">
		{@render children()}
	</main>
</div>

<style>...</style>

<!-- src/routes/+page.svelte -->
<script lang="ts">
	import PlaygroundLayout from '$lib/PlaygroundLayout.svelte';
	import App from '$lib/playground/App.svelte';
</script>

<PlaygroundLayout>
	<App />
</PlaygroundLayout>

中身を見てみると PlaygroundLayout.svelte は 公式のPlayground に模したページのコンポネント、 App.svlete は Playground で作成した中身が入ってるようです。

pnpm dev で実行するとページは下記のような感じです。

公式の Playground みたいな見た目をしてました。

正直いつ使うかぱっとみ思いつきませんでしたが、バグの報告時のリプロダクションを簡単にローカル環境に作れそうだとは思いました。