Open5

nextjs

fnecofneco

Next.js Learn Course メモ[1]

  • Cumulative Layout Shift はGoogleがウェブサイトのパフォーマンスとユーザー体験を評価するために使用する指標です。フレイアウトシフトは、ブラウザが最初にフォールバックフォントまたはシステムフォントでテキストをレンダリングした後、カスタムフォントが読み込まれ置き換わるときに発生する。この入れ替えによって、テキストのサイズ、間隔、レイアウトが変更され、周囲の要素が移動することがある。
  • <Image> の width, height は レイアウトのずれを防ぐために設定すべき。これらはソース画像と同じアスペクト比であるべき。
  • <Link>を使うと、JavaScriptでクライアントサイドナビゲーションを行うことができので、<a> タグによるfull page refresh を回避できる。
  • ナビゲーション体験を向上させるために、Next.jsはルートセグメントごとにアプリケーションを自動的にコード分割します。ルートによってコードが分割されるということは、ページが分離されるということです。特定のページがエラーをスローしても、アプリケーションの残りの部分は動作します。本番環境では、<Link>コンポーネントがブラウザのビューポートに表示されるたびに、Next.jsはバックグラウンドでリンクされたルートのコードを自動的にプリフェッチします。
  • デフォルトでは、Next.jsアプリケーションはReact Server Componentsを使用します。
    • Server Componentsはpromiseをサポートし、データフェッチなどの非同期タスクをよりシンプルに解決します。useEffectやuseState、データ取得ライブラリに手を伸ばすことなく、async/await構文を使用できます。
    • Server Componentsはサーバー上で実行されるため、高価なデータ取得やロジックをサーバー上に保持し、結果のみをクライアントに送信することができます。
    • Server Componentsはサーバー上で実行されるため、APIレイヤーを追加することなく、データベースに直接問い合わせることができます。
  • Pageを非同期コンポーネントにすることにより、awaitを使ってデータを取得することができる。
  • request waterfall: リクエスト・ウォーターフォールとは、リソース(コード、CSS、画像、データ)に対するリクエストが、リソースに対する別のリクエストが終了するまで開始されないことを指す。[2]
    • ウォーターフォールとは、前のリクエストの完了に依存する一連のネットワーク・リクエストのことである。データ・フェッチの場合、各リクエストは、前のリクエストがデータを返して初めて開始できる。
    • 一般的には、JavaScriptでは、Promise.all()またはPromise.allSettled()関数を使用して、すべてのリクエストを同時に、つまり並行して開始して対策する。
      • しかし、1つのデータリクエストが他のすべてのリクエストより遅い場合はどうなるのか?ダイナミック・レンダリングでは、アプリケーションは最も遅いデータ・フェッチと同じ速度しか出せません。
  • Static Rendering:
    • デフォルトでは、Next.jsはパフォーマンスを向上させるために routes をプリレンダリングします。
    • Static Rendering では、データのフェッチとレンダリングは、ビルド時(デプロイ時)または revalidation時にサーバー上で行われる。その後、結果をコンテンツ・デリバリー・ネットワーク(CDN)に配信し、キャッシュすることができます。
      • benefits
        • より高速なウェブサイト - プリレンダリングされたコンテンツはキャッシュされ、グローバルに配信されます。
        • サーバー負荷の軽減 - コンテンツがキャッシュされるため、サーバーはユーザーのリクエストごとにコンテンツを動的に生成する必要がありません。
        • SEO - プリレンダリングされたコンテンツは、ページが読み込まれた時点ですでに利用可能な状態になっているため、検索エンジンのクローラーがインデックスしやすくなります。これにより、検索エンジンのランキングを向上させることができます。
      • 利用場面
        • 静的レンダリングは、静的なブログ記事や製品ページなど、データのないUIやユーザー間で共有されるデータに便利
        • 定期的に更新されるパーソナライズされたデータを持つダッシュボードには適していない。
  • dynamic rendering:
    • リクエスト時(ユーザーがページにアクセスした時)に、各ユーザーに対してサーバー上でコンテンツがレンダリングされます。
    • benefits
      • リアルタイムデータ - ダイナミックレンダリングにより、アプリケーションはリアルタイムまたは頻繁に更新されるデータを表示できます。
      • ユーザー固有のコンテンツ - ダッシュボードやユーザープロファイルなど、パーソナライズされたコンテンツを提供し、ユーザーとの対話に基づいてデータを更新することが容易になります。
      • リクエスト時の情報 - 動的レンダリングでは、クッキーやURL検索パラメータなど、リクエスト時にしかわからない情報にアクセスできます。
  • 利用場面:
    • データが頻繁に変更されるアプリケーションに最適です。
  • 利用方法
    • サーバーコンポーネントやデータ取得関数の内部でunstable_noStoreと呼ばれるNext.js APIを使用すると、静的レンダリングを省略できます。
      • unstable_noStoreは実験的なAPIであり、将来変更される可能性がある。自分のプロジェクトで安定したAPIを使いたい場合は、Segment Config Optionを使用することもできます。
  • Streaming:
    • ストリーミングとは、route を小さな "チャンク "に分割し、準備ができ次第、サーバーからクライアントに順次ストリーミングするデータ転送技術である。
    • 利点
      • ストリーミングによって、遅いデータ・リクエストがページ全体をブロックするのを防ぐことができます。これにより、UIがユーザーに表示される前にすべてのデータがロードされるのを待つことなく、ユーザーはページの一部を見て操作することができます。
      • Reactの各コンポーネントはチャンクとみなすことができるので、ストリーミングはReactのコンポーネント・モデルと相性がよい。
    • Next.jsでストリーミングを実装する方法
      • ページレベルで、loading.tsxファイルを使用する。
        • loading.tsxはSuspenseの上に構築された特別なNext.jsファイルで、ページのコンテンツがロードされる間、代替として表示するフォールバックUIを作成することができます。
        • loading.tsx は layout.tsx の子コンポーネントであり、 静的であれば、すぐに表示される。動的コンテンツがロードされている間、ユーザーは layout.tsx 配下の静的なコンポーネントとやりとりすることができる。
        • ユーザーはページの読み込みが終わるのを待たずにナビゲートすることができます(これは中断可能なナビゲーション(interruptable navigation)と呼ばれます)。
      • 特定のコンポーネントに<Suspense>を使用する。
  • Route groups
    • 括弧()を使用して新しいフォルダを作成すると、その名前はURLパスに含まれません。
      • 例えば、/dashboard/(overview)/page.tsxの path は /dashboardになります。
    • URLパスの構造に影響を与えることなく、ファイルを論理的なグループにまとめることができます。
      • loading.tsx を特定の path にのみ適用させることができる。
      • アプリケーションをセクションに分けたり、大規模なアプリケーションのためにチームごとに分ける用途にも利用できる。
  • React Suspense
    • ページ全体のストリーミングするloading.tsxとは異なり、特定のコンポーネントをストリーミングすることができます。
    • 何らかの条件が満たされるまで(例えばデータが読み込まれるまで)、アプリケーションの一部のレンダリングを延期できます。
    • 利用方法
      • データフェッチを必要とするコンポーネントの中でフェッチする
      • データフェッチを必要とするコンポーネント(動的コンポーネント)を <Suspense /> に child として渡す
    • 利用場面
      • 遅いデータリクエストに依存するコンポーネントだけにSusppenseを使うことで、そのコンポーネントだけをストリーミングし、ページの残りのUIをすぐに表示する。
  • サスペンスの境界線をどこに置くか
    • 検討要素
      • ユーザーにどのようにページを体験してもらいたいか。
      • どのコンテンツを優先するか。
      • コンポーネントがデータ取得に依存している場合。
    • 一般的には、データの取得を必要なコンポーネントに移し、そのコンポーネントをサスペンスでラップするのがよい方法です。しかし、アプリケーションに必要であれば、セクションやページ全体をストリーミングしても問題はありません。
  • URL search params による状態管理(クライアントステートに代わる状態管理)
    • 利点
    • ブックマーク可能なURLと共有可能なURLです:検索パラメータはURL内にあるので、ユーザーは検索クエリとフィルタを含むアプリケーションの現在の状態をブックマークして、将来の参照や共有に利用することができます。
    • サーバーサイドレンダリングと初期ロード:初期状態をレンダリングするために、URLパラメータをサーバー上で直接 consume することができるため、サーバーレンダリングの処理が容易になります。
    • アナリティクスとトラッキング: 検索クエリとフィルタを直接URL内に持つことで、クライアントサイドのロジックを追加することなく、ユーザーの行動をトラッキングしやすくなります。
  • "use client"
    • このキーワードをファイルの冒頭に記述すると、イベント・リスナーやフックを使うことができます。
  • "use server"
    • このキーワードをファイルの冒頭に記述すると、ファイルからエクスポートされたすべての関数をサーバー関数としてマークすることができます。サーバー関数は、クライアントコンポーネントやサーバーコンポーネントにインポートすることができます。
  • searchParams prop
    • ページコンポーネントはsearchParamsというpropを受け取る
  • React Server Actions
    • 非同期コードをサーバー上で直接実行できる
      • 効果:
        • データを変更するためのAPIエンドポイントを作成する必要がなくなる
        • 効果的なセキュリティソリューションを提供し、さまざまなタイプの攻撃から保護し、データを保護し、許可されたアクセスを保証
          • POSTリクエスト、暗号化されたクロージャ、厳密な入力チェック、エラーメッセージのハッシュ化、ホストの制限などの技術によってこれを実現
    • 方法:
      • サーバー上で実行される非同期関数を記述し、クライアントまたはサーバーコンポーネントから呼び出す
      • Reactでは、<form>要素のaction属性を使ってアクションを呼び出すことができます。アクションは自動的に、取り込まれたデータを含むネイティブの FormData オブジェクトを受け取ります。
    • 利点
      • サーバー コンポーネント内でサーバー アクションを呼び出すことの利点: クライアントで JavaScript が無効になっている場合でもフォームは機能します。
      • Next.jsでは、サーバーアクションでフォームが送信されると、アクションを使用してデータを変更できるだけでなく、revalidatePathやrevalidateTagなどのAPIを使用して、関連するキャッシュを再検証することもできます
    • 実装:
      • "use server" キーワードをファイルの冒頭に記述すると、ファイルからエクスポートされたすべての関数をサーバー関数としてマークすることができます。
      • サーバー関数は、クライアントコンポーネントやサーバーコンポーネントにインポートすることができます。
      • アクションの中に "use server "を追加することで、サーバーコンポーネントの中に直接サーバーアクションを記述することもできます。
      • JS bindを使用してデータ(関数でいうところの引数)をServer Actionに渡すことができます。これにより、Server Actionに渡される値はすべてエンコードされます。
        • 例: const updateInvoiceWithId = updateInvoice.bind(null, invoice.id);
        • 注:隠し入力フィールドを使用する手もあります(例:<input type="hidden" name="id" value={invoice.id} />)。ただし、値はHTMLソースにフルテキストとして表示されるため、IDのような機密データには適していません。
  • action 属性
    • HTMLでは、action属性にURLを渡します。このURLはフォームデータの送信先(通常はAPIエンドポイント)になります。
    • Reactでは、action属性は特別なpropとみなされます。
  • Client-side Router Cache
    • ルートセグメントをユーザーのブラウザに一時的に保存するNext.jsの機能。
    • このキャッシュは、サーバーへのリクエスト数を減らしながら、プリフェッチとともに、ユーザーがルート間をすばやく移動できるようにします。
    • Next.jsのrevalidatePath関数でこのキャッシュをクリアできる
  • Dynamic Route Segments
    • Next.jsでは、正確なセグメント名がわからず、データに基づいてルートを作成したい場合に、ダイナミックルートセグメントを作成することができます。たとえば、ブログ記事のタイトルや商品ページなどです。フォルダの名前を角括弧で囲むことで、動的なルートセグメントを作成できます。たとえば、[id]、[post]、[slug]などです。
  • アクセシビリティ
    • 障害のある人を含め、誰もが使用できるウェブアプリケーションを設計し、実装することを指します。
    • キーボードナビゲーション、セマンティックHTML、画像、色、動画など、多くの分野をカバーする広大なトピックです。
  • Server-Side validation
    • benefits:
      • データベースにデータを送信する前に、データが期待される形式であることを確認する。
      • 悪意のあるユーザーがクライアント側のバリデーションをバイパスするリスクを減らす。
      • 何が有効なデータとみなされるかの真実の情報源を1つにする。
  • metadata:
    • Description Metadata
      • このメタデータは、ウェブページのコンテンツの概要を示すもので、検索エンジンの検索結果に表示されることが多い。
    • Keyword Metadata
      • ウェブページのコンテンツに関連するキーワードが含まれ、検索エンジンがページをインデックスするのに役立ちます。
    • Open Graph Metadata
      • ソーシャルメディアプラットフォームでウェブページが共有される際の表現方法を強化し、タイトル、説明文、プレビュー画像などの情報を提供します。
    • Favicon Metadata
      • ブラウザのアドレスバーまたはタブに表示されるファビコン(小さなアイコン)をウェブページにリンクします。
    • Metadata API
      • アプリケーションに
      • メタデータを追加するには、2つの方法があります:
        • Config-based
          • 静的な metadata オブジェクトまたは動的な generateMetadata 関数を layout.js または page.js ファイルにエクスポートします。
        • File-based
          • Next.jsには、メタデータ用に特別なファイルが用意されている。
            • favicon.ico, apple-icon.jpg, and icon.jpg: ファビコンやアイコンに使用
            • opengraph-image.jpg and twitter-image.jpg: ソーシャルメディアの画像
            • robots.txt: 検索エンジンのクロールに関する指示
            • sitemap.xml: ウェブサイトの構造に関する情報提供
脚注
  1. https://nextjs.org/learn?utm_source=next-site&utm_medium=homepage-cta&utm_campaign=home ↩︎

  2. https://tanstack.com/query/latest/docs/react/guides/request-waterfalls ↩︎

fnecofneco

https://www.freecodecamp.org/news/how-to-use-react-server-components/

React Server Components

Reactの哲学は、デザイン全体をコンポーネントと呼ばれる自己完結型の小さな断片に分割することを提案している。

従来のコンポーネントをクライアント・コンポーネントと呼ぶことにしよう。クライアント・コンポーネントはすべてJavaScriptの関数である。

伝統的に、Reactコンポーネントはクライアント側のJavaScript関数である。コンポーネントは、Reactアプリケーションの構成要素です。アプリケーションをクライアントにロードすると、コンポーネントはクライアントにダウンロードされ、Reactはそれらをレンダリングするために必要なことを実行する。

しかし、これには2つの大きな問題がある:

まず、ユーザーがリクエストを送信すると、アプリはリンクされたJavaScript、CSS、画像のような他のアセットとともにHTMLをダウンロードする。

クライアント・サイト(ブラウザ上)では、Reactがマジックを開始し、HTML構造をハイドレートする。HTMLを解析し、イベントリスナーをDOMにアタッチし、ストアからデータをフェッチする。こうして、サイトは完全に動作するReactアプリとなる。

しかし、重要なのは、クライアントで多くのことが起きているということだ。結局、クライアントでこのコードをすべてダウンロードすることになる。

多くの場合、プロジェクトの依存関係として外部ライブラリ(Nodeモジュール)が必要になります。これらの依存関係はすべてクライアント・サイドでダウンロードされることになり、余計にかさばることになる。

このような問題を理解していただけたなら、React Server Componentsがどのような機能を提供し、どのようにこれらの問題に対処できるかをご理解いただけると思います。

React Server Componentsは、サーバー上にあるため、ファイルシステムやデータストアのようなサーバーインフラにアクセスできる。
RSCを使えば、データ・フェッチ・ロジックをサーバーに移し(コンポーネントがネットワーク・コールなしでデータをフェッチするように)、サーバー自体で準備することができる。クライアントに戻ってくるデータは、うまく構築されたコンポーネントであり、その中にすべてのデータが収まっている。

RSCはサーバー上に留まり、サーバー上でレンダリングされます。RSCにはクライアントサイドに関連するものはありません。つまり、サーバー・コンポーネントにユーザー・インタラクティビティを追加することはできません。例えば、イベントハンドラや、useState、useReducer、useEffectのようなReactフックをサーバーコンポーネントで使用することはできません。
サーバーコンポーネントでは、localstorage、bluetooth、Web USBなどのブラウザWeb APIを使用することはできません。

クライアントとのインタラクションに関連するものはすべて、クライアント・コンポーネントを使い続けなければならない。

クライアント・コンポーネントとサーバー・コンポーネントを併用する方法

サーバーコンポーネントはクライアントコンポーネントをインポートしてレンダリングできます。
クライアント・コンポーネントの中でサーバー・コンポーネントを使いたい場合は、propsとして渡します。
サーバーコンポーネントをコンポーネント階層のルートに置き、クライアントコンポーネントをコンポーネントツリーのリーフの方に持っていくのがよいでしょう。
ユーザー・インタラクション(イベント・ハンドラ)とブラウザAPIへのアクセスは、リーフ・レベルのクライアント・コンポーネントで処理できる。

RSCはサーバー・サイド・レンダリング(SSR)の違い

サーバー・サイド・レンダリングでは、生のHTMLをサーバーからクライアントに送信し、クライアント側のJavaScriptはすべてダウンロードされる。ReactはHydrationプロセスを開始し、HTMLをインタラクティブなReactコンポーネントに変換する。SSRでは、コンポーネントはサーバーに留まらない。

Reactサーバーコンポーネントを使えば、コンポーネントはサーバー上に留まり、ネットワークの往復をすることなくサーバーインフラにアクセスできる。

SSRは、アプリケーションの初期ページの読み込みを高速化するのに便利です。アプリケーションでSSRとRSCを一緒に使っても問題はありません。

fnecofneco

Architecture [1]

Next.js Compiler

Next.js CompilerはSWCを使ってRustで書かれている。
Babel による transform と、出力バンドルの minify のためのTerserを置き換えるものです。
既存のBabelコンフィギュレーションがある場合、またはサポートされていない機能を使用している場合、アプリケーションはNext.jsコンパイラをオプトアウトし、引き続きBabelを使用します。

SWCはコンパイルにもバンドルにも使用できる。コンパイルでは、最新のJavaScriptの機能を使用しているJavaScript / TypeScriptファイルを取り込み、すべての主要なブラウザでサポートされている有効なコードを出力します。[2]

Turbopack (beta)

JavaScriptとTypeScriptに最適化された incremental bundler。
Rustで書かれている。
(webpack を置き換えるもの?)

脚注
  1. https://nextjs.org/docs/architecture ↩︎

  2. https://swc.rs/ ↩︎