kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Next.js 9.3 で使えるようになった getStaticProps と getServerSideProps

2020年3月にリリースされた Next.js 9.3 から,アプリケーションをビルドする戦略として以下3種類の API が使えるようになった.Next.js Blog では「Next-gen Static Site Generation (SSG) Support」と紹介されていた.

  • getStaticProps
    • 「ビルド時」にデータを取得する
  • getStaticPaths
    • 「ビルド時」にデータを取得する(Dynamic Routing を作る)
  • getServerSideProps
    • 「リクエスト時」にデータを取得する

nextjs.org

今までの getInitialProps は?

レンダリング時に API からデータを取得するなど,今まで使ってきた getInitialProps はどうなるの?と気になると思う.ドキュメントに書いてある通り,Next.js 9.3 以降は getInitialProps ではなく getStaticPropsgetServerSideProps を使うことが推奨 (Recommended) になっている.とは言え,今までの getInitialProps も非推奨とまでは書いてなく,引き続き使える.今後実装するなら,getStaticPropsgetServerSideProps を使っていくと良さそう.

nextjs.org

なお,getStaticPropsgetServerSideProps は Node.js コンテキスト(サーバサイド)で実行される.よって,今まではフロントエンドにも対応した fetch API として,例えば isomorphic-unfetch などを使っていたけど,サーバサイドだけなら node-fetch を使える.Next.js 9.3 に対応したサンプルコードも node-fetch を使うように更新されていたりする.

data-fetch テンプレート

実際に getStaticPropsgetServerSideProps を試しながら理解を深めるため,create-next-app で使える data-fetch テンプレートの実装を参考に試した.既に getStaticProps を使った実装に更新されている.さらに今回は TypeScript を使うために with-typescript テンプレートをベースにした.create-next-app に関しては先週の記事にまとめた.

kakakakakku.hatenablog.com

検証環境

今回は Next.js 9.3.5 を使う.

$ npm view next version
9.3.5

また,動作確認をするサンプルコードを pages 直下に実装した.

$ tree pages
pages
├── get-server-side-props.tsx
└── get-static-props.tsx

サンプルコード : get-static-props.tsx

まず,getStaticProps を使ったサンプルコード get-static-props.tsx を載せる.ビルド時に GitHub API から Next.js の Star⭐️ 件数を取得する.また Link コンポーネントを使って遷移できるように /get-server-side-props へのリンクも実装した.

import React from 'react'
import Link from 'next/link'
import fetch from 'node-fetch'

type Props = {
  stars: number
}

function Index({ stars }: Props) {
  return (
    <div>
      <p>Next.js has {stars} ⭐️</p>
      <Link href="/get-server-side-props">
      <a>Go to getServerSideProps</a>
      </Link>
    </div>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return {
    props: {
      stars: json.stargazers_count,
    },
  }
}

export default Index

サンプルコード : get-server-side-props.tsx

次に,getServerSideProps を使ったサンプルコード get-server-side-props.tsx を載せる.リクエスト時に GitHub API から Next.js の Star⭐️ 件数を取得する.また Link コンポーネントを使って遷移できるように /get-static-props へのリンクも実装した.

import React from 'react'
import Link from 'next/link'
import fetch from 'node-fetch'

type Props = {
  stars: number
}

function Index({ stars }: Props) {
  return (
    <div>
      <p>Next.js has {stars} ⭐️</p>
      <Link href="/get-static-props">
        <a>Go to getStaticProps</a>
      </Link>
    </div>
  )
}

export async function getServerSideProps() {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return {
    props: {
      stars: json.stargazers_count,
    },
  }
}

export default Index

ビルド

yarn build を実行すると,実装された getStaticPropsgetServerSideProps を参考に判定される./get-static-props「● (SSG)」となり /get-server-side-props「λ (Server)」となる.

$ yarn build

(中略)

Page                            Size     First Load JS
┌ ○ /                           1.8 kB         59.9 kB
├ ○ /404                        2.61 kB        60.7 kB
├ λ /get-server-side-props      1.84 kB        59.9 kB
└ ● /get-static-props           1.85 kB        59.9 kB

(中略)

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)(Static)  automatically rendered as static HTML (uses no initial props)(SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

✨  Done in 5.0s.

動作確認

実際に画面にアクセスして確認した.ビルド時の Star⭐️ 件数は 46914 だった(動作確認中にどんどん増えてて驚いた!).ビルド時と変化させるために Star⭐️ を付けたり消したりした.以下にイメージ画像を載せておく.

f:id:kakku22:20200420102656p:plain

1. /get-static-props

getStaticProps の場合はビルド時にデータを取得しているため,素早く表示された.5ms ~ 10ms 程度.直接 http://localhost:3000/get-server-side-props にアクセスすると Content-Typetext/html で返ってきた.Link コンポーネントをクリックしてフロントエンド側で画面遷移をすると Content-Typeapplication/json で以下のように返ってきた.

{
  "pageProps": {
    "stars": 46914
  },
  "__N_SSG": true
}

2. /get-server-side-props

getServerSideProps の場合はリクエスト時にデータを取得しているため,少し時間がかかる.getStaticProps と同じく,直接 http://localhost:3000/get-server-side-props にアクセスすると Content-Typetext/html で返ってきた.Link コンポーネントをクリックしてフロントエンド側で画面遷移をすると Content-Typeapplication/json で以下のように返ってきた.

{
  "pageProps": {
    "stars": 46918
  },
  "__N_SSP": true
}

まとめ

Next.js 9.3 で使えるようになった getStaticPropsgetServerSideProps の理解を整理するためにサンプルコードを実装しながら試した.getStaticProps はビルド時にデータを取得し,getServerSideProps はリクエスト時にデータを取得する.詳しくは Data fetching のドキュメントにも載っている.Static Site Generation (SSG) を使っていくぞー!

nextjs.org