Next.jsにおけるfetchのタイミングと使い方

2022-08-02

最近になってようやく Next.js における fetch の叩くべきタイミングや使い分けがわかるようになってきました。

今回は、現時点の自分なりの考えを書いていこうと思います。


前提

Next.js 環境下で fetch を叩く場合、call されるタイミングは大きく 3 つにわかれます。

  • build 時(getStaticProps)
  • render 前(getServerSideProps)
  • render 後(useEffect, SWR, React Query など)

ただし getStaticProps については build 時に以外のタイミングでも call される可能性があります。

各々の関数について

getStaticProps

Static な、つまり静的な HTML に対し、サーバー側で api の call などを行い、props を通してデータを出力する目的で主に使用されます。

build 時に実行されるため、Cookie を扱うことができない点に注意が必要です。

build 時に実行され静的な HTML を出力するため、画面の描画はもっとも早いです。

また build 時以外に実行されるタイミングは、以下のとおりです。

  • build 時には存在しなかったページが作成された
  • revalidate に設定した時間を過ぎてページにアクセスがあった
  • api 内で res.revalidate が実行された

個人的には getServerSideProps より getStaticProps を積極的に使うべきだと考えています。

getServerSideProps

ページにアクセスがあった際、render 前にサーバー側で api の call などを行い、props を通してデータを流し込む目的で主に使用されます。

render 前に実行されるため、Cookie を扱うことが可能です。

ただし render 前に実行されるため画面の描画は遅くなるデメリットが存在し、ユーザビリティが低下する恐れもあります。

useEffect, SWR, React Query

ページにアクセスがあった際、render が行われた後にクライアント側で api の call などを行い、state を通してデータを流し込む目的で主に使用されます。

個人的には api の向き先は同ドメインの /api 以下に向ける方針が無難だと思っています。

render 後に実行されるため Cookie を扱うことも可能ですが、api を call する場合は /api 以下で Cookie を扱うほうが無難かと思われます。

render 後に実行されるため画面の描画は早いですが、一瞬データが格納されていない状態が表示されます。

使い分け

api 周りで Cookie を扱う場合

getServerSideProps および useEffect, SWR, React Query のみ使用可能です。

api のレスポンスデータを SEO に反映する必要がある場合

getStaticProps および getServerSideProps のみ対応可能です。

最強の組み合わせ

ログインが不要なケースでは getStaticProps + SWR または React Query の組み合わせがオススメです。

ただし以下の点は考慮が必要です。

  • 静的な HTML が出力されるため、サーバー側のファイル容量が増える
  • 実装量が増え、求められる知識レベルも高いため、開発コストは高いです

ログインが必要なケースでは SWR または React Query のみで十分なケースが多いです。

ただしサーバー側に認証系を寄せる場合、middleware または getServerSideProps に実装が求められてくると思います。

getServerSideProps の使いみち

getServerSideProps を用いて実装を行うと、ログインの必要性にかかわらずあらゆるケースへ対応が可能となります。

ただし画面の描画があからさまに遅くなるため、使い所を見極めて使用する必要があります。

ファーストリリースは getServerSideProps で実装して、その後 getStaticProps などを使用して最適化を行うというのもアリかもしれません。

実装のコツ

getServerSideProps や getStaticProps 内で api の call を行う場合、どの程度実装をサーバー側に寄せるか悩んでしまいますが。

個人的には、たとえば axios を使用するのであれば response.data をそのまま props に流し込むのが無難かなーと思っています。

なぜなら、たとえば SWR を組み合わせた場合、response.data をそのまま state に格納するケースがほとんどだと思われますので、非常にシンプルかつ保守が容易な実装となります。


そんな感じです。

© 2018 kk-web