2021/08/11

ブログ詳細編(getStaticPropsとgetStaticPathsについて理解する)

@ 酒井悠宇

ダイナミックルーティング実装時のgetStaticPathsとgetStaticPropsがやっていることがあまり理解できていないので、この記事でいい感じに理解していきたいと思います。

ブログ詳細ページ作成中〜。
まだ途中ですがデプロイしておきます。
https://micro-cms-bvfyqomuw-sakai-141014.vercel.app/blog/ku00q5qnb

getStaticPropsとは


要点をまとめるとこんな感じです。
・getStaticPropsは、Next.jsで事前ビルド(pre-rendering)を行う際に、外部データが必要な時に使用する関数。
・事前ビルドというのは、「ユーザーがwebページにアクセスする前にページを表示するのに必要なHTMLを構成しておく」という意味。
・Next.jsではこの事前ビルドのことをpre-renderingと呼ぶ。
・Next.jsはデフォルトで全ページをpre-renderingしている。

pre-renderingには二種類あります。
「外部データを必要としないpre-rendering」と「外部データを必要とするpre-rendering」です。

外部データを必要としない時
・Next.jsプロジェクト内のディレクトリに格納してある画像ファイルを一覧表示するページを作成したい時

外部データを必要とする時
・外部APIから取得してきたブログデータを一覧表示するページを作成したいとき

pre-renderingを行う時かつ、それに外部データを必要するときに使用するのがgetStaticPropsです。

開発環境ではリクエストごとに実行される関数ですが、本番環境ではビルド時に実行される関数です。

getStaticPathsとは


getStaticPathsを使用する時というのは、ダイナミックルーティングを実装したい時だと思うので、まずはダイナミックルーティングについて解説します。

「ダイナミックルーティングを実装する」というのは、「複数のURLに対応したページファイルを作る」ということと同じ意味です。

ブログ一覧ページで、ある一つのブログのタイトルをクリックすると、ブログの詳細ページに飛ぶ。みたいな実装をしたい時にこのダイナミックルーティングを使います。なぜならブログ一個一個にルーティングを手動で設定していくのはめんどくさいからです。

そして、このダイナミックルーティングを実装するときに使用するのがgetStaticPathsです。

まずは日本語訳してみましょう。

get(入手する)Static(静的な)Paths(パスを)

「静的なパスを入手する」らしいです。

URLによって表示される内容が変わる動的なファイルを作ったなら、表示する内容を決定するURLは誰がいつみても変わらない、つまり静的でなければいけません。

だからダイナミックルーティングとgetStaticPathsはセットです。

では実際にダイナミックルーティングを実装してみましょう。

まずはダイナミックルーティング用のファイルを作ります。
Next.jsではファイル名に[]を使うとそれがダイナミックルーティング用のファイルであるという意味になります。
こんかいはブログ記事に対してダイナミックルーティングを実装したいので、pagesディレクトリ配下blogというディレクトリを作成し、そのファイル内に[id].tsxというファイルを作成します。
ちなみにこの[]内はidじゃなくても任意に決めていいです。

それでは実際にgetStaticPathsで静的なパスを入手していきたいと思います。
コードは以下のようになりました。

export const getStaticPaths: GetStaticPaths = async () => {
  //blogのデータ全部くれ
  const data: Data = await client.get({ endpoint: "blog" });
  //アクセスしうるページのパスの入ったオブジェクトの配列としてまとめておく
  const pathList = data.contents.map((Blog) => {
    return {
      params: {
        id: Blog.id,
      },
    };
  });

  return {
    paths: pathList,
    //アクセスしうるパス以外のパスに対するアクセスの対処
    fallback: false,
  };
};


今回はmicrocmsからブログデータをfetchしてきています。
blogというエンドポイントに対してデータくれよって頼んでます。
データはオブジェクト形式になっています。
この中にブログに関するデータが全部入ってます。

 const data: Data = await client.get({ endpoint: "blog" });


data.contentは配列です。中にはブログ一つ一つの情報がオブジェクトで順番に入っています。
これをmapで回しでブログのid(そのブログがそのブログであると判別できる一意の値)を取得しています。

const pathList = data.contents.map((Blog) => {
  return {
    params: {
      id: Blog.id,
    },
  };
});


pathListを実際に実行してみるとこんな感じで返ってきました。
全体としてはオブジェクトの配列で、オブジェクトの中にはparamsというキーのバリューにブログのidがオブジェクトで入っています。
getStaticPathsの仕様上、id情報に対してparamsをキーに指定するみたいです。


そして最終的なgetStaticPathsの返り値は以下のようになっています。
id情報の配列と、fallbackには想定していないidでアクセスされた場合の挙動を設定しています。falseというのは404ページを表示するという意味です。

return {
  paths: pathList,
  //アクセスしうるパス以外のパスに対するアクセスの対処
  fallback: false,
};


getStaticPaths内の処理で、「アクセスし得るページのパス」を取得し、「アクセスしうるパス以外のパスに対するアクセスの対処」も設定することができました。

ssgを実現するコード

getStaticPaths 関数は、ビルド時に静的にレンダリングするパスの一覧を決めておく関数です。


それではこれを元に、getStaticPropsでidに対応するブログの情報をpre-renderingする処理を記述していきます。
コードは以下のようになりました。

export const getStaticProps: GetStaticProps = async ({params}) => {
  const id = params.id as string;
  const data: Blog = await client.get({ endpoint: "blog", contentId: id });
  return {
    props: {
      data: data,
    },
  };
};


getStaticPropsが引数に受け取る{params}には、getStaticPathsが返り値として返す「アクセスし得るページのパスのリスト」内にある{ params: {id:"id名"} }オブジェクトが一つずつ入ります。そのidを元にそれに対応したブログ情報をエンドポイントを指定してfetchします。

const id = params.id as string;
const data: Blog = await client.get({ endpoint: "blog", contentId: id });


あとはfetchしてきた情報をpropsとして受け取れるようにreturnすれば完成です。

  return {
    props: {
      data: data,
    },
  };


ブログページがpre-renderingされ爆速に動きます。

まとめ

・getStaticPropsは外部データを必要とするpre-renderingを行いたいときに使用する。
・getStaticPaths 関数は、ビルド時に静的にレンダリングするパスの一覧を決めておく関数。
・getStaticPathsとgetStaticPropsでいい感じにダイナミックルーティングを実装できる。

いい感じにgetStaticPropsとgetStaticPathsを理解できたと思います。
最後までごらんいただきありがとうございました〜!

© 2021 powerd by UnReact