Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

このチュートリアルでは、React サーバー コンポーネントを理解し、その知識をもとにアプリ用のシンプルなビュー カウンターを一緒に構築します。実装を進めたい場合は、[プロジェクトの設定] に進んでください。

React サーバー コンポーネントについて

React サーバー コンポーネントがどのように機能するかを理解するために、クライアントサイド レンダリング (CSR) とサーバーサイド レンダリング (SSR) について簡単に説明します。

クライアントサイド レンダリング (CSR)

CSR では、ほとんどのレンダリング作業はクライアント側のブラウザで行われます。

<オル>
  • ユーザーがサイトをリクエストします。
  • サーバーは HTML ファイルと CSS ファイルおよび JS ファイルへのリンクを送信します。
  • クライアントは JS リソースをダウンロードします。
  • クライアントはコンテンツなしでページをレンダリングします。
  • クライアントはサーバーの API からデータを取得します。
  • クライアントはコンテンツを含むページを再レンダリングします。
  • React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

    サーバーサイド レンダリング (SSR)

    SSR では、サーバーはリクエストごとに完全な HTML コンテンツを生成し、それをクライアントに送信します。

    <オル>
  • ユーザーがサイトをリクエストします。
  • サーバーは実際の HTML ファイルをレンダリングしますが、まだインタラクティブではありません。
  • クライアントは JS リソースをダウンロードします。
  • クライアントで、hydrateRoot() を使用します。 React コンポーネントの関数、イベント リスナー、状態、およびその他の対話機能は、サーバーによって生成された既存の DOM 要素に関連付けられます。これはハイドレーションとして知られています。 .
  • クライアントはサーバーの API からデータを取得します。
  • クライアントはコンテンツを含むページを再レンダリングします。
  • React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

    SSR の利点

    • SEO の向上 :検索エンジンのクローラーは完全にレンダリングされた HTML を読み取ることができるため、SSR は SEO に適しています。
    • 初期読み込みの高速化 :完全な HTML コンテンツがレンダリングされてサーバーから送信されるため、ユーザーはページのコンテンツをすぐに確認できます。

    SSR のデメリット

    • ナビゲーションが遅くなる :新しいページのリクエストごとに、サーバーから HTML を完全にリロードするための往復通信が必要です。
    • サーバー負荷の増加 :サーバーはページのレンダリングでほとんどの作業を行うため、複数のリクエストを処理するにはより多くのリソースが必要になる場合があります。

    React サーバー コンポーネント

    RSC は、コンポーネントをサーバー上で完全にレンダリングできるようにする React の機能です。

    <オル>
  • サーバーがデータを取得します。
  • サーバーはコンテンツを含むアプリをレンダリングします。
  • クライアントは JS リソースをダウンロードします。
  • ハイドレーションはクライアント内で行われます。
  • 注: サーバー コンポーネントは完全にサーバー上でレンダリングされ、JS バンドルには含まれず、ハイドレートされません。したがって、ステップ 3 と 4 はクライアント コンポーネントに対して行われます。

    React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

    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

    環境セットアップ

    <オル>
  • Upstash コンソール → Redis に移動し、新しいデータベースを作成します。
  • React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

    <オル>
  • REST API セクションまで下にスクロールし、.env に切り替えます。 タブをクリックして、次のステップのために環境変数をコピーします。
  • React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

    <オル>
  • .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 にアクセスして、ビュー カウンタの動作を確認してください。

    React Server コンポーネントを使用してリアルタイム ビュー カウンターを構築する

    クライアント コンポーネントのセットアップとの比較

    クライアント コンポーネントを使用した実装については、ブログ投稿「Next.js ブログへのビュー カウンターの追加」を参照してください。

    React サーバー コンポーネントを使用すると、前のセクションで説明した他の利点に加えて、次のような利点があります。

    • 別個の API が必要なくなりました。
    • 型チェックの利点を備えた、コンポーネントとそのロジックのシンプルな統合ビューを提供します。

    デプロイ

    次のコマンドを使用して、サイトを Vercel にデプロイできます。

    vercel

    最後の言葉

    サーバー コンポーネントとクライアント コンポーネントの両方の長所を組み合わせることで、アプリケーションのパフォーマンスと対話性の適切なバランスをとることができます。このガイドが、React Server コンポーネントを効果的に活用するタイミングについて情報に基づいた決定を下すのに役立つことを願っています。


    1. 切断、更新、クラッシュが発生しても持続する回復力のある LLM ストリームを作成する

      私たちが構築しているもの この記事では、簡単に存続できる非常に耐久性の高い LLM ストリームを構築します。 ネットワーク障害 ページが更新されます ウェブサイトの閉鎖 ノートパソコンの蓋を閉める ボーナス:複数のデバイス (携帯電話やラップトップなど) で同時に同じストリームを表示できます。 . ストリームを中断しようとしても、接続が切断されている間はバックグラウンドで継続され、戻った後もスムーズに継続されます。これは信じられないほどです。 ユーザーエクスペリエンス。 耐久性のある LLM ストリームのデモ 👇 インスピレーション AI を使用して構築する場合、AI 応答を

    2. サーバーレスRedisとReactNativeを使用したアプリ内アナウンス

      モバイルアプリケーションでは、アプリのエンドユーザーに情報、警告、またはガイダンスを送信する必要がある場合があります。これを行う1つの方法は、アプリ内アナウンスをユーザーに送信することです。 このブログ投稿では、サーバーレスRedisを使用してユーザーにアナウンスを送信する方法を示すモバイルアプリケーションを開発します。 React Nativeを使用してモバイルアプリケーションを開発し、アプリに直接接続されているサーバーレスRedis用のUpstashを開発します。 アプリ内アナウンスとは何ですか? アプリ内アナウンスは、重要なことをエンドユーザーに通知したり、アクションについて通知した