2025年人気No.1のNext.jsで、最新ツールとウェブを作る！ | エピソード10 機能拡張とメンテナンス

## 目標
- ブログに新機能を追加してユーザー体験を向上させる。
- 分析ツールを統合してサイトのパフォーマンスを追跡する。
- デバッグとNext.jsのアップデートの方法を学ぶ。
- 長期的なプロジェクト運営のアドバイスを得る。

---

## 1. 新機能の追加：検索機能
ブログに簡単な検索機能を追加します。

### `app/search/page.tsx`の作成：
```tsx
'use client';

import { useState } from 'react';
import { supabase } from '../../lib/supabase';

export default function Search() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<any[]>([]);

  const handleSearch = async () => {
    const { data } = await supabase
      .from('posts')
      .select('*')
      .ilike('title', `%${query}%`);
    setResults(data || []);
  };

  return (
    <div className="max-w-2xl mx-auto p-6">
      <h1 className="text-3xl font-bold text-blue-600 mb-6">投稿を検索</h1>
      <div className="mb-4">
        <input
          type="text"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          className="w-full p-2 border rounded"
          placeholder="タイトルで検索..."
        />
        <button
          onClick={handleSearch}
          className="mt-2 bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
        >
          検索
        </button>
      </div>
      <ul className="space-y-4">
        {results.map((post) => (
          <li key={post.id} className="bg-white p-4 rounded shadow">
            <a href={`/posts/${post.id}`} className="text-xl font-semibold text-blue-500 hover:underline">
              {post.title}
            </a>
            <p className="text-gray-600">{post.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}
```

### ナビゲーションに追加：
`app/layout.tsx`のヘッダーに検索リンクを追加：
```tsx
<Link href="/search" className="hover:underline">検索</Link>
```

---

## 2. 分析ツールの統合
サイトのトラフィックを追跡するためにGoogle Analyticsを追加します。

### 手順：
1. **Google Analyticsの設定**：
   - Google Analyticsで新しいプロパティを作成し、トラッキングID（例：`G-XXXXXXXXXX`）を取得。
2. **Vercel Analyticsとの併用**：
   - Vercelダッシュボードで「Analytics」を有効化（無料枠あり）。
3. **Google Analyticsの実装**：
   - `app/layout.tsx`にスクリプトを追加：
     ```tsx
     import './globals.css';
     import Link from 'next/link';
     import { auth } from 'next-auth';
     import { signIn, signOut } from 'next-auth/react';

     export const metadata = {
       title: 'Next.js 2025ブログ',
       description: '2025年の最新技術で作られたブログサイト',
     };

     export default async function RootLayout({ children }) {
       const session = await auth();

       return (
         <html lang="ja">
           <head>
             <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
             <script
               dangerouslySetInnerHTML={{
                 __html: `
                   window.dataLayer = window.dataLayer || [];
                   function gtag(){dataLayer.push(arguments);}
                   gtag('js', new Date());
                   gtag('config', 'G-XXXXXXXXXX');
                 `,
               }}
             />
           </head>
           <body className="font-sans antialiased">
             <header className="bg-blue-800 text-white p-4">
               <nav className="max-w-4xl mx-auto flex justify-between items-center">
                 <Link href="/" className="text-xl font-bold">ホーム</Link>
                 <div className="space-x-4">
                   <Link href="/about" className="hover:underline">About</Link>
                   <Link href="/add-post" className="hover:underline">投稿追加</Link>
                   <Link href="/search" className="hover:underline">検索</Link>
                   {session ? (
                     <>
                       <span>{session.user?.name}</span>
                       <button onClick={() => signOut()} className="hover:underline">ログアウト</button>
                     </>
                   ) : (
                     <button onClick={() => signIn('google')} className="hover:underline">Googleでログイン</button>
                   )}
                 </div>
               </nav>
             </header>
             <main>{children}</main>
             <footer className="bg-gray-200 p-4 text-center text-gray-600">
               © 2025 Next.js学習シリーズ
             </footer>
           </body>
         </html>
       );
     }
     ```

---

## 3. デバッグとNext.jsのアップデート
長期的な運用にはデバッグとアップデートが重要です。

### デバッグ：
- **ログの確認**：Vercelの「Logs」タブでエラーを特定。
- **ローカルテスト**：`npm run dev`で問題を再現し、コンソールを確認。

### Next.jsのアップデート：
1. 最新バージョンを確認：
   ```
   npm outdated
   ```
2. アップデート実行：
   ```
   npm install next@latest
   ```
3. リリースノートを確認し、破壊的変更に対応。

---

## 4. 長期運営のアドバイス
- **定期的なバックアップ**：Supabaseのデータをエクスポート。
- **ユーザーからのフィードバック**：コメント欄やフォームを追加して意見を収集。
- **スケーラビリティ**：トラフィック増加に備え、Vercelのプランを検討。
- **コードの整理**：不要なコードを削除し、リファクタリングを続ける。

---

## 実践：拡張されたブログ
- **検索機能**：タイトルで投稿を検索。
- **分析**：Google Analyticsで訪問者を追跡。
- **メンテナンス**：デバッグとアップデートを実施。

**確認**：
- `/search`で検索が動作し、Analyticsダッシュボードにデータが記録されることを確認。

---

## エピソード10の終了
- ブログに検索機能を追加し、分析ツールを統合しました。
- 長期的なメンテナンスの基礎を築きました。
- これでシリーズ完結！お疲れ様でした！

---

この記事が役に立ったと思ったら、ぜひ「いいね」を押して、ストックしていただければ嬉しいです！シリーズを通して学んだことをぜひ活用してください！