Closed7
nextのSSR、ISRについて考える(本当にgetServerSidePropsはそこまで避けるべきものか?)
- ISRはgetStaticPropsを利用していて、「Static Generate」とあるが、実態としてSSRと同じようにサーバー上で処理することで動いている
-
yarn start
することで動いている - このためvercel上や、CloudRunなどでは動き、serverlessな環境では動かせない
- 個人的な感覚で言えば、この挙動はサーバー起動しているアプリケーションの前段にnginxでキャッシュを仕掛けているような構成と似たようなものではないかと感じている(Railsのページキャッシュのようなものと言っても近そう)
-
- ただnext.jsのドキュメント上で言えばこれをStatic Generationと呼んでるっぽい気がする
- ServerSideとStaticの違いは
req
,res
へアクセス出来ることと定義している節を感じる。
- ServerSideとStaticの違いは
- ISRが
getStaticProps
を利用しており、req
へアクセス出来ない事によって、ユーザーのログイン状態をしたレンダリングが出来ないようになっている。- これは確かに良いことで、通常のWebアプリケーションでよくある、愚直に全部キャッシュしてしまってログイン情報が漏れてしまったみたいな事故に繋がりづらそう。
- 例えばURLに認証トークンを仕込むような形式だと事故は起きうる(例えば
/order/[orderId]
みたいなページで認証をすべきところでしてなかったケースなど?)
つまり本当は
- server target
- ISR
- SSR
- serverless target
- export html
な気がするのだが見せ方的に
- dynamic generate
- SSR
- static generate
- ISR
- export html
の区分をしているように見えるのが腹落ちしない原因っぽい
getServerSideProps
を使うとき・使わないとき
-
When should I use getStaticProps?
にはThe data can be publicly cached (not user-specific).
とある一方でWhen should I use getServerSideProps?にはYou should use getServerSideProps only if you need to pre-render a page whose data must be fetched at request time.
とあって、露骨にgetStaticProps
推し(getServerSideProps
下げ)を感じる - ではuser-specifiedなデータを出したいときはどうするか?という点についてはFetching data on the client sideということでClientでfetchしろ、と誘導している
ほんとに?
- 個人的には上記については微妙に疑義が残る
- 例えばユースケースとして、ログインしている人に追加なコンポーネントを出すという場合であればこれはその通りclientでfetchするのが妥当というのは理解できる
- 一方でそれ以外のユースケースとして、全てのページがログイン必須な場合や、UXとSEOの兼ね合いで、初回レンダリングの時点で分離させたいというケースでgetServerSideProps存在するであろうと推察する(後述)
全ページログイン必要な場合
- この場合、クライアントフェッチでも確かに可能であるが、その場合全ページにおいてAPIとpagesを分離して書く必要が出てくる。
- そうなると結局RESTにおけるgetな部分は
getServerSideProps
の機能として書いてしまうほうが楽ではいか?と体感では感じる - 管理画面的なノリであれば、paginationすらAPIを通さず
/someItem/list/[pageNum]
的にしてgetServerSidePropsに任せたほうが楽に感じる
- そうなると結局RESTにおけるgetな部分は
-
getServerSideProps
で例えばRDBアクセスなどをした場合、connection poolingを適切に考えなければ適切に動かないという問題がありそうだ- 一方でこの問題は
getServerSideProps
で行おうが/api
以下のNextApiHander
で行おうがつきまとう問題となる。 - 特にその結果別なAPIをproxyするような場合であれば、結局
getServerSideProps
でやったほうが怠惰に進められそうだ。
- 一方でこの問題は
UXとSEOの兼ね合いで初回レンダリングを変えたい場合。
- 例えば「会員登録して続きを読む」みたいな場合を想定する
- この場合、ログイン済みの会員には初回レンダリングからすべて表示されている状態にして、非会員ならマスクさせるという風にしたい
- この場合は結局素直に
getServerSideProps
を使ったほうが素直ではなかろうか? -
getServerSideProps
を使わないで解決方法を考える- 解決方法1: URLを会員用/非会員用で分ける
- なんとなく過去の経験からするとSEO担当者から嫌がられそうだ・・・
- あと会員が目的のページに遷移するのに1クリック増える事になりそう
- 解決方法2: 非会員の状態(マスクあり)でpre-renderingして、client side fetchをして会員の場合はマスクを置き換える
- これで解決は出来るが、おそらくローディング後にガチャっとずれて(あの現象名前なんて言うんだっけ・・・)若干ストレスの貯まる画面になりそうだ
- 解決方法1: URLを会員用/非会員用で分ける
ガチャッとずれる現象はLayout Shiftですかね…?
ちなみにZennで記事や本を表示するときは、ISR + クライアント側でのSWR(的なもの)という感じにしています。ただ、getStaticProps
とクライアント側の2箇所でAPIリクエストをするのはややこしいので、本当にパフォーマンスを優先したいページだけISRを使うようにしています。
このスクラップは2020/12/27にクローズされました