React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する
このチュートリアルでは、React サーバー コンポーネントを理解し、その知識をもとにアプリ用のシンプルなビュー カウンターを一緒に構築します。実装を進めたい場合は、[プロジェクトの設定] に進んでください。
React サーバー コンポーネントについて
React サーバー コンポーネントがどのように機能するかを理解するために、クライアントサイド レンダリング (CSR) とサーバーサイド レンダリング (SSR) について簡単に説明します。
クライアントサイド レンダリング (CSR)
CSR では、ほとんどのレンダリング作業はクライアント側のブラウザで行われます。
<オル>

サーバーサイド レンダリング (SSR)
SSR では、サーバーはリクエストごとに完全な HTML コンテンツを生成し、それをクライアントに送信します。
<オル>hydrateRoot() を使用します。 React コンポーネントの関数、イベント リスナー、状態、およびその他の対話機能は、サーバーによって生成された既存の DOM 要素に関連付けられます。これはハイドレーションとして知られています。 .

SSR の利点
- SEO の向上 :検索エンジンのクローラーは完全にレンダリングされた HTML を読み取ることができるため、SSR は SEO に適しています。
- 初期読み込みの高速化 :完全な HTML コンテンツがレンダリングされてサーバーから送信されるため、ユーザーはページのコンテンツをすぐに確認できます。
SSR のデメリット
- ナビゲーションが遅くなる :新しいページのリクエストごとに、サーバーから HTML を完全にリロードするための往復通信が必要です。
- サーバー負荷の増加 :サーバーはページのレンダリングでほとんどの作業を行うため、複数のリクエストを処理するにはより多くのリソースが必要になる場合があります。
React サーバー コンポーネント
RSC は、コンポーネントをサーバー上で完全にレンダリングできるようにする React の機能です。
<オル>注: サーバー コンポーネントは完全にサーバー上でレンダリングされ、JS バンドルには含まれず、ハイドレートされません。したがって、ステップ 3 と 4 はクライアント コンポーネントに対して行われます。

RSC の利点
- 効率的なデータ処理: データの取得はデータベースに近いサーバーに移動されます。これにより、クライアントとサーバーの往復がなくなり、パフォーマンスが向上します。
- クライアント上の JavaScript サイズの削減 :React サーバー コンポーネントはクライアントに JavaScript を送信しないため、バンドル全体のサイズが削減され、パフォーマンスが向上します。
- 初期ページ読み込みの高速化 :サーバー上でコンポーネントを事前レンダリングすると、クライアントは完全にレンダリングされた HTML をより速く受信できるようになり、First Contentful Paint (FCP) までの時間が短縮されます。
- SEO の改善 :コンテンツはサーバー側で完全にレンダリングされるため、検索エンジンによるコンテンツのクロールとインデックス作成が容易になります。
RSC の課題
- 状態とライフサイクル :React サーバー コンポーネントはブラウザ API (
useStateなど) にアクセスできません。 、useEffect)、サーバー上でレンダリングされるため。 - クライアント側での対話機能なし :React Server コンポーネントは、動的な更新や対話性を目的としたものではありません。アプリのインタラクティブな部分にはクライアント コンポーネントを使用する必要があります。
React サーバー コンポーネントの使用
Next.js の React サーバー コンポーネント
デフォルトでは、Next.js はサーバー コンポーネントを使用します。これらは 3 つの異なる方法でレンダリングされます。
- 静的レンダリング (デフォルト): ルートはビルド時にレンダリングされます。 または、データの再検証後にバックグラウンドで実行されます。
- 動的レンダリング: ルートはリクエスト時にユーザーごとにレンダリングされます。 .
- ストリーミング: UI はサーバーから徐々にレンダリングされます。
React サーバー コンポーネントを使用する必要がある場合 ?
次の場合は React サーバー コンポーネントを使用する必要があります :
- 頻繁に変更されない、静的で非インタラクティブなコンテンツがある。
- クライアントに送信される JavaScript を減らしてパフォーマンスを向上させたいと考えています。
- SEO はアプリケーションにとって重要です。
- 大量のデータ取得や計算タスクをサーバーにオフロードしたいと考えている。
次の場合はサーバー コンポーネントに反応すべきではありません :
- コンポーネントには、クライアント側の対話性、状態、またはフックが必要です。
- ブラウザ API にアクセスする必要があるか、リアルタイムの更新が必要である
- 重いクライアント側のロジックやユーザー固有のコンテンツを含む複雑なページを構築しているとします。
よくある落とし穴
クライアント コンポーネントは完全にクライアント上でレンダリングされるわけではありません
これらはクライアントとサーバーの両方でレンダリングされます。サーバー コンポーネントと区別するために、クライアント コンポーネントという名前が付けられています。
‘use server’ ディレクティブはサーバーアクション用です。
デフォルトでは、Next.js はサーバー コンポーネントを使用するため、何も指定する必要はありません。クライアント コンポーネントを使用する場合は、‘use client’ を追加します。 サーバーモジュールとクライアントモジュール間の境界を宣言するディレクティブ。 ‘use server’ これはサーバー アクションに使用されるまったく異なるディレクティブです。 、これはこのブログ投稿の範囲を超えています。
プロジェクトのセットアップ
Vercel のブログ テンプレートを使用します。
pnpm create next-app --example https://github.com/vercel/examples/tree/main/solutions/blog blog サンプルをローカルで実行して、どのようになるかを確認できます。
cd blog
pnpm dev
@upstash/redis をインストールしましょう :
pnpm add @upstash/redis 環境セットアップ
<オル>

.env に切り替えます。 タブをクリックして、次のステップのために環境変数をコピーします。

.env を作成します ファイルを作成し、環境変数を貼り付けます。UPSTASH_REDIS_REST_URL=<YOUR_URL>
UPSTASH_REDIS_REST_TOKEN=<YOUR_TOKEN> ビュー コンポーネントのセットアップ
/app/components/views.tsx を作成します :
import { headers } from 'next/headers'
import { Redis } from "@upstash/redis"
const redis = Redis.fromEnv();
async function view(slug: string, ip: string) {
// Hash the IP address to anonymize it
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(ip));
const hash = Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("");
// Deduplicate views
const newView = await redis.set(`deduplicate:${hash}:${slug}`, true, {
nx: true, // Only set the key if it doesn't exist
ex: 24 * 60 * 60, // Expire the key after 24 hours
});
if (newView) {
await redis.incr(`pageviews:${slug}`); // Increment the view count
}
}
export default async function Views({ slug }: { slug: string }) {
// Get the IP address of the user
const header = headers()
const ip = (header.get('x-forwarded-for') ?? '127.0.0.1').split(',')[0]
// Increment the view count
await view(slug, ip)
// Get the view count
const views = await redis.get<number>(`pageviews:${slug}`) || 0
return (
<p className="text-sm text-neutral-600 dark:text-neutral-400">
{views} views
</p>
)
}
ビュー コンポーネントのインポートと表示
/app/blog/[slug]/page.tsx を編集します :
...
import Views from 'app/components/views'
...
<div className="flex justify-between items-center mt-2 mb-8 text-sm">
<p className="text-sm text-neutral-600 dark:text-neutral-400">
{formatDate(post.metadata.publishedAt)}
</p>
<Views slug={post.slug} />
</div>
... http://localhost:3000/blog/vim にアクセスして、ビュー カウンタの動作を確認してください。

クライアント コンポーネントのセットアップとの比較
クライアント コンポーネントを使用した実装については、ブログ投稿「Next.js ブログへのビュー カウンターの追加」を参照してください。
React サーバー コンポーネントを使用すると、前のセクションで説明した他の利点に加えて、次のような利点があります。
- 別個の API が必要なくなりました。
- 型チェックの利点を備えた、コンポーネントとそのロジックのシンプルな統合ビューを提供します。
デプロイ
次のコマンドを使用して、サイトを Vercel にデプロイできます。
vercel 最後の言葉
サーバー コンポーネントとクライアント コンポーネントの両方の長所を組み合わせることで、アプリケーションのパフォーマンスと対話性の適切なバランスをとることができます。このガイドが、React Server コンポーネントを効果的に活用するタイミングについて情報に基づいた決定を下すのに役立つことを願っています。
-
切断、更新、クラッシュが発生しても持続する回復力のある LLM ストリームを作成する
私たちが構築しているもの この記事では、簡単に存続できる非常に耐久性の高い LLM ストリームを構築します。 ネットワーク障害 ページが更新されます ウェブサイトの閉鎖 ノートパソコンの蓋を閉める ボーナス:複数のデバイス (携帯電話やラップトップなど) で同時に同じストリームを表示できます。 . ストリームを中断しようとしても、接続が切断されている間はバックグラウンドで継続され、戻った後もスムーズに継続されます。これは信じられないほどです。 ユーザーエクスペリエンス。 耐久性のある LLM ストリームのデモ 👇 インスピレーション AI を使用して構築する場合、AI 応答を
-
サーバーレスRedisとReactNativeを使用したアプリ内アナウンス
モバイルアプリケーションでは、アプリのエンドユーザーに情報、警告、またはガイダンスを送信する必要がある場合があります。これを行う1つの方法は、アプリ内アナウンスをユーザーに送信することです。 このブログ投稿では、サーバーレスRedisを使用してユーザーにアナウンスを送信する方法を示すモバイルアプリケーションを開発します。 React Nativeを使用してモバイルアプリケーションを開発し、アプリに直接接続されているサーバーレスRedis用のUpstashを開発します。 アプリ内アナウンスとは何ですか? アプリ内アナウンスは、重要なことをエンドユーザーに通知したり、アクションについて通知した