ルーティング

ユーザーがストアフロントドメインでリクエストを行うと、pwa-kit-react-sdk/ssr/server/react-renderingで定義されている render という Express.js ハンドラーによって処理されます。ハンドラーはレスポンスとしてレンダリングするコンポーネントを選択します。このタイプのコンポーネントはルートと呼ばれます。レンダリングで使用可能なルートは、app/routes.jsxroutes と呼ばれるオブジェクト配列で定義されています。

ルート配列は、React Router で定義されているように、ルート構成の形状に従います。routes 配列の各オブジェクトは、以下のプロパティをもつことができます:

キータイプ説明参照ドキュメント
pathExpress-style 文字列、文字列の配列、または正規表現受信リクエストパスと一致するかどうかが比較されるパスReact Router API → Route コンポーネント → path
component関数 (routes.jsx にインポート)パスがリクエストと一致する場合にレンダリングするコンポーネントReact Router API → Route コンポーネント → component
exactブール値パスが完全一致でなければならないかどうかを決定しますReact Router API → Route コンポーネント → exact

新しく生成されたプロジェクトでは、ホーム、PLP、PDP などの多くの標準的な e コマースページのオブジェクトが routes 配列にすでに含まれています。

では、React アプリは、任意のリクエストに対してレンダリングするための適切なコンポーネントをどのようにして選択するのでしょうか。この場合、React Router ライブラリを使用して、リクエストされたパスと一致する path 文字列が見つかるまで、routes 配列のルート構成オブジェクトが順番に検索されます。

React Router には path 文字列の作成のために多くのオプションが用意されています。同じコンポーネントに対して複数のパスを指定し、正規表現を使用してパターンに従うパスを一致できます。

React Router は、Retail React App 全体でナビゲーションを実装するためにも使用されます。たとえば、すべてのハイパーリンクは React Router の Link コンポーネントを使用します。React Router には、ブラウザーの履歴やクエリパラメーターなどにアクセスできるその他のコンポーネントが用意さています。

React Router の使用に関する詳細は、公式ドキュメントを参照してください。(バージョン 5 のドキュメントのみを参照してください。その他のバージョンでは異なるパターン一致システムが使用されています。)

routes 配列で指定されている各コンポーネントは、自動的に PWA Kit React SDK の高階コンポーネントrouteComponent 関数で強化されます。routeComponent の作成に使用されるベースクラスによって、いくつかの静的メソッドが定義されます。これには、ストアフロントデベロッパーがカスタマイズ可能な 2 つの重要なメソッド、getPropsshouldGetProps が含まれます。

getProps メソッドは、props オブジェクトを経由して routeComponent にデータを供給するために使用します。これらのデータは API リクエストからフェッチします。

routeComponent は、routes 配列のコンポーネントを強化する際に、そのコンポーネントのプロパティの内部で getProps という関数を探します。ここに関数を定義しておくと、強化されたコンポーネントのメソッドとして表示されます。routes 配列のすべてのコンポーネントに対して関数を定義する必要はありません。レンダリングの前にデータをフェッチするコンポーネントだけで構いません。

定義される getProps 関数は、promise を返します。promise が解決されると、コンポーネントがレンダリングされるときに、props オブジェクトを経由して強化されたコンポーネントに、解決された値が渡されます。

routes 配列のコンポーネントがレンダリングされる場合は、コンポーネントの getProps メソッドが 1 つの JavaScript オブジェクトとともに提供されます。このオブジェクトは、レンダリングのコンテキストに応じて以下のプロパティをもちます。

キータイプ説明可用性その他
paramsオブジェクトExpress-style ルート文字列で指定されているルートパラメーターに対応するオブジェクトプロパティを含みます。たとえば、ルート /user/:name がある場合、リクエストパスの :name の値は params.name として使用できます。デフォルト値は {}クライアント側とサーバー側の両方Express API → Request → req.params
reqオブジェクトExpress によって強化された Node のリクエストオブジェクトのバージョン。HTTP リクエストを表現し、クエリ文字列、パラメーター、ボディ、HTTP ヘッダーなどのプロパティをもちます。サーバー側のみExpress API → Request
resオブジェクトHTTP リクエストを受け取った際に Express アプリが送信する HTTP レスポンスを表現します。サーバー側のみExpress API → Response
location文字列リクエストの URL。クライアント側とサーバー側の両方Express API の一部ではありません。

getProps 関数のエラーを処理するには、2 つのオプションがあります。

最初のオプションは、pwa-kit-react-sdk/ssr/universal/errors からインポートできる HTTPError オブジェクトをスローすることです。HTTPError をスローすると、専用の Error コンポーネントがレンダリングされます。

2 番目のオプションは、props を使用して、レンダリングされるコンポーネントにエラーを知らせ、カスタムのエラー処理ロジックで使用できるようにすることです。

以下に、両方のエラー処理のアプローチを使用する例を示します:

getProps で返されたオブジェクトは、シリアル化されて、ページソースの __PRELOADED_STATE__ という名前のオブジェクトを経由して、レンダリングされる HTML に埋め込まれます。

レンダリングされる HTML のサイズを小さく抑えるために、getProps で返すデータは最小限にしてください。たとえば、可能であれば API リクエストからのレスポンス全体を返すことは避けるようにします。

サーバー側でレンダリングされるページのバージョンをブラウザーでプレビューするには、URL の最後に?__server_only を追加します。このクエリパラメーターは ハイドレーション プロセスを停止するため、ブラウザーはレンダリングを行わず、サーバー側のレンダリング後にページが変更されません。__PRELOADED_STATE__ オブジェクトの pretty-print バージョンを表示するには、クエリ文字列に ?__server_only&__pretty_print を追加します。

クライアント側のレンダリング中にユーザーが後続のページにナビゲートすると、そのページはすぐにレンダリングされます。レンダリングは getProps によるデータのフェッチ中に行われる場合があるため、未定義の props を処理するための条件コードを常にコンポーネントに書き込みます。また、props が未定義の際には、プレースホルダーコンポーネントをレンダリングすることを覚えておいてください (Chakra UI の Skeleton と同様)。

クライアント側では、コンポーネントの render メソッドは getProps が解決する前と後に呼び出されます。コンポーネントに渡された isLoading プロップを使用して、読み込み画面をレンダリングするかどうかを決定します。

getProps で複数の HTTP リクエストを行う場合、並行して行うようにします。並行して行えない場合は、クライアント側レンダリングへの移行を検討します。

クライアント側でデータを取得するだけの場合、getProps ではなく、コンポーネントで React フックを使用します。

すべてのルートで同じコードを実行したい場合は、特殊コンポーネントの 1 つである App コンポーネントに属する getProps 関数を定義します。特殊コンポーネントは、複数のルートで共有される機能の追加に使用されます。App コンポーネントやその他の特殊コンポーネントについて詳しくは、特殊コンポーネントのガイドを参照してください。

shouldGetProps メソッドを使用して、getProps メソッドを呼び出すタイミングをコントロールします。サーバー側のレンダリング中は、shouldGetProps は 1 回のみ呼び出されます。クライアント側のレンダリング中は、React のライフサイクルメソッドの componentDidUpdate が呼び出されるたびに呼び出されます。

デフォルトでは、getPropslocation.pathname の値が変更されるたびに getProps を呼び出します。routes 配列内の各コンポーネントのデフォルトの動作は、shouldGetProps と呼ばれる独自の関数をコンポーネントのプロパティとして定義することで上書きできます。shouldGetProps をカスタマイズして、リクエストを検査し、特定のリクエストに対してのみ getProps を呼び出すことができます。

ソースコードをレビューして、ルーティングについての理解を深めてください。以下にあげる Retail React App の主要なファイルを確認してください。

  • app/routes.jsx: パスの一致 (指定されたルートパラメーターを含む) の Express-style 構文を示します。
  • app/pages/product-detail/index.jsx: PDP 用のこのサンプルコンポーネントには、getPropsshouldGetProps の両方のためのカスタム関数が含まれています。
  • app/components/_app_config/index.jsx: 広範囲の構成コードと、アプリ全体での getProps 関数が含まれています。

PWA Kit ドキュメントを参照する際は、Retail React App のアーキテクチャガイドを必ずお読みください。