技術とかの雑なToday I Learnedメモ

Next.jsとGatsby.jsの比較の記事

Next.js と Gatsby.js の比較

リーディングリスト消化

Next.js は Gatsby.js を倒さない

このサイトを作るときに Next.js と Gatsby.js を比較してどっちにしようか迷っていて、結局 Next.js を使うことにした上で「Gatsby.js 使わなくても Next.js でカバーできそうだな」と思っていた。

実際 Gatsby.js を使って何かを作ったことがあるわけではないので、こういう記事を読めるのはありがたい。

Gatsby.js で実装する場合

サンプルコードを見ると、各記事のページごとに forEach でcreatePagesとブログ記事一覧のページで 1 度createPagesを呼んでいるっぽい。

Next.js ではgetStaticPropsgetStaticPathsが分かれているけど、Gatsby.js は関数ひとつで path と props(というかページを構成するためのデータ)を一度に作れるみたい。

Next.js で実装する場合

記事の各ページの path はgetStaticPaths、内容はgetStaticPropsがページ数分あり、記事一覧ページはパスが動的ではないのでgetStaticPropsが 1 回呼ばれる。

比較

Gatsby.js は API へのリクエストは一度で済む。

Next.js は path と props で別々にリクエストするため、リクエスト数が多い。が、ISR という便利な機能がある。

ISR

ISR のサンプルコードを読んだときにあれ?となったので調べた。

以下、記事内のサンプルコード引用

export async function getStaticPaths() {
-   const res = await fetch('https://.../blogs')
-   const blogs = await res.json()
-   const paths = blogs.map((blog) => `/blogs/${blog.id}`)
  return {
-     paths,
+     paths: [],
     fallback: true,
  }
}

export async function getStaticProps({ params }) {
 const res = await fetch('https://.../blogs')
 const blogs = await res.json()
 const blog = blogs.find(blog => params.id === blog.id)

 return {
   props: {
     blog,
   },
+   revalidate: 15 * 60,
 }
}

getStaticPathspaths: []にして大丈夫なんだっけ?と思って、昔の自分が書いた投稿を読み直した。

Next.js の SSG と ISR とその他

getStaticPropsrevalidateを指定することで ISR することができる。

まずビルド時にはgetStaticPathsでは空配列を返しているから、記事ごとのパスは生成されていない。

fallback: trueを指定しているから、データを取得する必要がある部分以外がレンダリングされた HTML を返すはず。

いったんフォールバック用のページを表示するが、そのページに対応したデータがあればデータ取得が走り、その後はキャッシュされて 2 回目以降のリクエストで SSG と同じ挙動になる、はず。

ここらへん理解したと思ったけど意外と曖昧だ……。

こうすることでビルド時のリクエストは 0(paths に何も指定してないから?)になり、記事ページへの最初のリクエストでfallback: trueの挙動によりデータ取得が走って、その後のリクエストではキャッシュが返されて、revalidateに指定された時間後のリクエストでは再びリクエストが走る、という感じ?

強みと弱み

Gatsby.js はビルド時のページ生成が細かく設定でき、リクエストも少ないが、ページ数に応じてビルド時間が増えていくのと、静的サイトの作成目的しか利用できない。

Next.js は、ISR やフォールバックがあるけどビルド時に ISR を使わないと N+1 リクエストになる。

ISR の Next.js、SSG の Gatsby.js として棲み分けできる。

その他

nextjs の ISR を使うときの fallback 指定について理解するまでの話

サンプルコードだとうまく動かなそう?

router.isFallbackの間はローディングを表示するなどしないといけないっぽい。