🐶

Next.jsでReactを強化!SSRとRSCの基礎を学ぶ

2025/02/25に公開

最近Reactを勉強し始めて、ようやくアプリを一つ作成できるようになりました。そんな時に最近よく聞く単語「SSRって何?」「Next.jsって必要なの?」「RSC??」そんな疑問を最近感じ改めて調べることにしました

Web開発で感じていた課題

あるWebサービスを作ることになり、Reactを使って開発を始めましたが、いくつかの問題に直面します:

  1. 表示が遅い!
// よくある従来のReactコンポーネント
function ProductList() {
  const [products, setProducts] = useState<Product[]>([]);
  
  useEffect(() => {
    // ユーザーは以下の3ステップを待たないといけない...
    // 1. JavaScriptのダウンロード
    // 2. Reactの起動
    // 3. データの取得
    fetch('/api/products').then(res => res.json()).then(setProducts);
  }, []);

  return <div>{/* ... */}</div>;
}
  1. Googleから見つかりにくい!

    • なぜなら、最初はからのページしかないから...
    • JavaScriptを実行しないとコンテンツが見えない...
  2. コードが複雑になっていく!

    • データ取得のコードがあちこちに散らばる
    • エラー処理が大変
    • パフォーマンスの改善が難しい

レンダリング方式をSSRに

SSR(サーバーサイドレンダリング)は、「サーバーで完成したページを作って送る」という考え方です。

CSRとSSRの違い

Next.jsで解決

Next.jsって何?

Next.jsは、ReactをベースにしたフルスタックWebフレームワークです。シンプルなReactよりも多くの機能を提供し、モダンなWebアプリケーション開発をサポートします。

Next.jsの主な特徴

  • フォルダとファイル構造に基づいて自動的にルートが生成される
  • APIエンドポイントを簡単に作成できる
  • 画像、フォント、スクリプトの最適化

Next.jsとViteの違い

以前React Viteでの実装方法について紹介しました。
https://zenn.dev/xronotech/articles/11e671bf0315e7
Viteは高速な開発環境を提供するビルドツールであるのに対し、Next.jsはフルスタックのフレームワークです。主な違いは以下の通りです:

目的の違い

Vite: 主に開発サーバーとビルドツールとして機能し、高速な開発体験を提供します。
Next.js: ルーティング、SSR、SSG、APIルートなど、アプリケーション全体の機能を提供するフレームワークです。

レンダリング戦略

Vite: 基本的にはクライアントサイドレンダリング(CSR)向けのツールで、SSRには追加の設定が必要です。
Next.js: SSR、SSG、CSR、ISRなど、様々なレンダリング方法を簡単に実装できます。

ファイル構造とルーティング

Vite: ルーティングは別途ライブラリ(react-router-domなど)を導入する必要があります。
Next.js: ファイルシステムベースのルーティングが組み込まれており、ファイル構造がそのままURLパスになります。

用途に応じた選択

Viteを選ぶとき:

既存のReactアプリの開発環境を高速化したい
シンプルなSPAを作成したい
特定のフレームワークに縛られたくない

Next.jsを選ぶとき:

SEO対策が重要なWebサイトを作る
サーバーサイドの機能も含めた完全なWebアプリを構築したい
フォルダ構造によるルーティングを活用したい
React Server Components(RSC)を使いたい

RSC(React Server Components)って何?

RSCは「サーバーで動くReactコンポーネント」です。React Server Componentsは、Next.js 13から導入された新しいReactの機能です。これまでのReactは基本的にブラウザで動いていましたが、RSCはサーバーで動きます。

RSCの利点

  • データアクセスの簡素化
    サーバー上で直接データベースやAPIにアクセスできる
    クライアントとサーバー間の往復が減る

  • バンドルサイズの削減
    サーバーコンポーネントのコードはクライアントに送信されない
    クライアントが受け取るJavaScriptが少なくなる

  • セキュリティの向上
    重要なデータやAPIキーをクライアントに公開せずに済む

まずはプロジェクトを作ってみる

npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm run dev

ファイル構造

my-nextjs-app/
├── app/             # ここにページを作っていきます
│   ├── page.tsx     # トップページ
│   └── about/       # aboutページのフォルダ
│       └── page.tsx # aboutページ
├── components/      # 再利用するパーツ
└── public/         # 画像などの静的ファイル

サーバーコンポーネントとクライアントコンポーネント

Next.jsのApp Routerでは、デフォルトですべてのコンポーネントがサーバーコンポーネントになります。

サーバーコンポーネントの例

import { Post } from '@/types/blog';

async function BlogPage() {
  // サーバー上で直接データを取得
  const posts: Post[] = await db.posts.findMany();
  
  return (
    <div className="max-w-4xl mx-auto py-8">
      <h1>ブログ記事一覧</h1>
      <div className="grid gap-6">
        {posts.map((post: Post) => (
          <article key={post.id}>
            <h2>{post.title}</h2>
            <p>{post.content.substring(0, 100)}...</p>
          </article>
        ))}
      </div>
    </div>
  );
}

export default BlogPage;

クライアントコンポーネントの例

'use client'; // この指示子でクライアントコンポーネントを宣言

import { useState } from 'react';

interface LikeButtonProps {
  postId: string;
}

function LikeButton({ postId }: LikeButtonProps) {
  const [likes, setLikes] = useState<number>(0);
  
  return (
    <button onClick={() => setLikes(likes + 1)}>
      いいね! ({likes})
    </button>
  );
}

export default LikeButton;

動的ルーティングを使ったページ

// app/blog/[id]/page.tsx
async function BlogPost({ params }: { params: { id: string } }) {
  const post = await getPost(params.id);
  
  return (
    <article>
      <h1>{post.title}</h1>
      <Content content={post.content} />
      {/* クリックイベントが必要な部分だけクライアントコンポーネントに */}
      <LikeButton postId={post.id} />
    </article>
  );
}

ボタンクリックとかはどうするの?

ユーザーの操作が必要な部分は、従来通りクライアントコンポーネントとして書きます:

// components/LikeButton.tsx
'use client'; // これでクライアントコンポーネントになる

function LikeButton({ postId }: { postId: string }) {
  const [likes, setLikes] = useState(0);
  
  return (
    <button onClick={() => setLikes(likes + 1)}>
      いいね! ({likes})
    </button>
  );
}

まとめ

  1. Next.jsの便利なところ

    • ルーティングが簡単
    • SSRが簡単
    • 画像最適化も簡単
  2. SSRで表示速度が爆速

    • ユーザーの待ち時間を減らせる
    • SEOも改善できる
  3. RSCの考え方

    • サーバーでできることはサーバーで
    • クライアントは必要な部分だけに
株式会社Xronotech

Discussion