🙆‍♀️

Next.js開発者がSvelteを学ぶ理由と始め方

2025/03/12に公開

こんにちは!今回はNext.jsでの開発経験がある方が、なぜSvelteを学ぶべきか、そしてどのように始めれば良いのかについて解説します。私自身、「AI駆動開発」(田村悠著)という本でSvelteが使われているのを見て興味を持ち、学び始めました。

きっかけ:AI駆動開発とSvelte

「AI駆動開発」という本では、生成AIを活用した開発手法が解説されていますが、そのサンプルコードにSvelteが使われていました。GitHubのai-driven-development-book-codeリポジトリでコードを見てみると、シンプルながらも強力な構文に興味を惹かれました。

例えば、このようなシンプルなコードでページが作れるのです:

<h1>Svelteのサンプルです</h1>
<h2>まずはSvelteの使い方を学びましょう</h2>
<p>Svelteはフロントエンドフレームワークです。</p>

これだけでコンポーネントとして機能するのは驚きでした。Next.jsなら最低でもReactのimport文やexport default関数が必要になりますよね。

Next.jsとSvelteの比較

まずは両者の違いを理解しましょう。

特徴 Next.js Svelte
基本構成 Reactベース 独自コンパイラ
コード量 比較的多い 少ない
仕組み 仮想DOM使用 直接DOM操作
バンドルサイズ 大きめ 小さい
学習曲線 やや急 緩やか
コミュニティ 非常に大きい 成長中
企業サポート Vercel コミュニティ主導
フルスタック 標準機能 SvelteKit

なぜNext.js開発者がSvelteを学ぶべきか

Next.jsの経験がある人がSvelteを学ぶ価値は十分にあります:

  1. 新しい考え方を学べる: 仮想DOMに依存しないアプローチを理解できます
  2. コード量の削減: 同じ機能をより少ないコードで実装する方法を学べます
  3. パフォーマンス意識: より効率的なフロントエンド開発の考え方が身につきます
  4. 視野の拡大: 一つのフレームワークに縛られない柔軟な思考ができるようになります

Svelteの基本:サンプルコードで学ぶ

それでは、基本的なSvelteコンポーネントを見てみましょう。

1. 基本的なコンポーネント

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

<h1>Hello {name}!</h1>
<button on:click={() => name = 'Svelte'}>
  Click me
</button>

<style>
  h1 {
    color: #ff3e00;
  }
</style>

このシンプルなコードで、変数の宣言、表示、イベント処理、スタイリングがすべて一つのファイルで完結しています。Next.jsのReactコンポーネントと比べるとかなりスッキリしていますね。

2. リアクティブな状態管理

<script>
  let count = 0;
  
  // リアクティブな宣言
  $: doubled = count * 2;
  
  function increment() {
    count += 1;
  }
</script>

<button on:click={increment}>
  カウント: {count}
</button>

<p>2倍の値: {doubled}</p>

$:構文を使うことで、リアクティブな変数を簡単に宣言できます。これはReactの useMemoフックに似ていますが、もっとシンプルです。

3. 条件付きレンダリングとループ

<script>
  let items = ['りんご', 'バナナ', 'オレンジ'];
  let showList = true;
</script>

<button on:click={() => showList = !showList}>
  {showList ? '非表示' : '表示'}
</button>

{#if showList}
  <ul>
    {#each items as item}
      <li>{item}</li>
    {/each}
  </ul>
{/if}

{#if}{#each}というブロックを使って、条件付きレンダリングやループが書けます。JSXの {}内にJavaScript式を書くReactとは異なり、専用の構文があるのが特徴です。

Svelteを始める手順

  1. 環境構築:
# Svelteのプロジェクトを作成
npm create svelte@latest my-svelte-app

# 依存関係のインストール
cd my-svelte-app
npm install

# 開発サーバーの起動
npm run dev
  1. フォルダ構造:
my-svelte-app/
├── src/
│   ├── app.html     # HTMLテンプレート
│   ├── routes/      # ページコンポーネント
│   ├── lib/         # 共有コンポーネント・関数
  1. SvelteKitの基本ルーティング:
src/routes/
├── +page.svelte     # ルートページ (/)
├── about/
│   └── +page.svelte # Aboutページ (/about)
└── api/
    └── +server.js   # APIエンドポイント (/api)

生成AIアプリケーション開発とSvelte

生成AIのWebアプリを開発する場合、Svelteは特に以下の点で優れています:

  1. 高速な初期ロード: バンドルサイズが小さいため、アプリが素早く読み込まれます
  2. 滑らかなUI: 効率的なDOM更新で、ストリーミングレスポンスの表示がスムーズ
  3. 直感的なコード: シンプルな構文でAI関連の複雑なロジックを整理しやすい

OpenAI APIを使ったSvelteアプリの実装例

実際にOpenAI APIを使用したテキスト生成アプリの実装例を見てみましょう。以下は完全に動作するコードです。

こちらで実際にクローンすれば誰でも触れるようになっているので、参考にしてください!

https://github.com/fumifumi0831/svelte-ai-demo.git

フロントエンドコンポーネント (+page.svelte)

<script>
  let prompt = '';
  let response = '';
  let loading = false;
  
  async function generateText() {
    loading = true;
    try {
      const res = await fetch('/api/generate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ prompt })
      });
    
      const data = await res.json();
      response = data.text;
    } catch (error) {
      console.error('Error:', error);
      response = 'エラーが発生しました';
    } finally {
      loading = false;
    }
  }
</script>

<div class="container">
  <h1>AI テキスト生成</h1>
  
  <textarea bind:value={prompt} placeholder="プロンプトを入力してください"></textarea>
  
  <button on:click={generateText} disabled={loading || !prompt}>
    {#if loading}
      生成中...
    {:else}
      生成する
    {/if}
  </button>
  
  {#if response}
    <div class="response">
      <h2>AI応答:</h2>
      <p>{response}</p>
    </div>
  {/if}
</div>

<style>
  .container {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
  }
  
  textarea {
    width: 100%;
    height: 150px;
    margin-bottom: 10px;
    padding: 10px;
    font-family: inherit;
    border: 1px solid #ccc;
    border-radius: 4px;
  }
  
  button {
    padding: 10px 20px;
    background-color: #ff3e00;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-weight: bold;
  }
  
  button:disabled {
    background-color: #ccc;
    cursor: not-allowed;
  }
  
  .response {
    margin-top: 20px;
    padding: 15px;
    background-color: #f9f9f9;
    border-radius: 4px;
    white-space: pre-wrap;
  }

  h1 {
    color: #ff3e00;
    margin-bottom: 20px;
  }
</style>

OpenAI APIセットアップ (src/lib/openai.js)

import OpenAI from 'openai';

// API設定
const apiKey = import.meta.env.OPENAI_API_KEY;

if (!apiKey) {
  console.error('OpenAI APIキーが設定されていません。.envファイルにOPENAI_API_KEYを設定してください。');
}

// OpenAIのクライアントを初期化
export const openai = new OpenAI({
  apiKey: apiKey,
  dangerouslyAllowBrowser: false // サーバーサイドでのみ使用する設定
});

/**
 * テキスト生成関数
 * @param {string} prompt ユーザーからのプロンプト
 * @returns {Promise<string>} 生成されたテキスト
 */
export async function generateText(prompt) {
  try {
    const completion = await openai.chat.completions.create({
      messages: [{ role: "user", content: prompt }],
      model: "gpt-3.5-turbo",
      temperature: 0.7,
      max_tokens: 500
    });

    return completion.choices[0].message.content;
  } catch (error) {
    console.error('OpenAI APIエラー:', error);
    throw new Error('テキスト生成中にエラーが発生しました');
  }
}

APIエンドポイント (src/routes/api/generate/+server.js)

import { json } from '@sveltejs/kit';
import { generateText } from '$lib/openai';

/**
 * POST /api/generate
 * @param {Request} request
 */
export async function POST({ request }) {
  try {
    const { prompt } = await request.json();
  
    if (!prompt || prompt.trim() === '') {
      return json({ error: 'プロンプトを入力してください' }, { status: 400 });
    }

    // OpenAI APIを使用してテキスト生成
    const generatedText = await generateText(prompt);

    return json({
      text: generatedText
    });
  } catch (error) {
    console.error('Error generating text:', error);
    return json({ error: 'テキスト生成中にエラーが発生しました' }, { status: 500 });
  }
}

環境変数の設定

.envファイルをプロジェクトのルートに作成し、OpenAIのAPIキーを設定します:

OPENAI_API_KEY=your_api_key_here

このコードを使用すれば、簡単にSvelteKitとOpenAI APIを連携させたアプリケーションを構築できます。APIキーはサーバーサイドでのみ使用され、クライアントに漏れることはありません。

まとめ:Next.jsとSvelteは対立ではなく共存

Next.jsとSvelteは、どちらが優れているというよりも、異なる状況で輝くフレームワークです。Next.jsはエコシステムの豊かさと大規模プロジェクトでの安定性、Svelteはシンプルさとパフォーマンスがそれぞれの強みです。

生成AIを活用したアプリケーション開発では、特にSvelteの軽量さと効率的なDOM更新が威力を発揮します。OpenAI APIなどの外部サービスと連携する場合も、SvelteKitのサーバーサイド機能を使えば安全かつシンプルに実装できます。

Next.jsの経験がある方は、週末プロジェクトや小規模アプリでSvelteを試してみると、新しい視点やアイデアが得られるでしょう。特に生成AIのプロトタイプ開発には、Svelteのシンプルさと低いオーバーヘッドが魅力的です。

最終的には両方のツールを理解していることで、プロジェクトに応じて最適な選択ができるようになります。フロントエンド開発の世界は常に進化しているので、新しい技術に触れることは非常に価値があります。

Svelteを学んでみて、あなたのフロントエンド開発の視野が広がることを願っています!

最後に

私は2つのプラットフォームで生成AIに関する発信を行なっております。

生成AIサービスの考察を見たい方へ

生成AIサービスの動向やや具体的な内容は、noteで詳しく解説しています。

noteプロフィール: @mizupee

日々の生成AI分析を追いたい方へ

毎日1つの生成AIサービスを分析するTwitter投稿「#100DaysofAI」もぜひフォローください。簡潔なポイント分析とアイデア共有を継続中です。

Twitter: @mizupee

Discussion