🦔

Next.jsでSSGしてみよう

2024/06/20に公開

概要

みなさん、こんにちは!アルダグラムでエンジニアをしている大木です。
今回は Next.js でSSG(Static Site Generation) を試した記録を残そうかなと思います。
弊社ではLPやコーポレートサイトで Gatsby.js を利用しています。Gatsby.js の便利な側面もある一方で、(主観ですが)直近はアップデートが鈍化している傾向にあり、技術移行も踏まえて検証をしないといけないなと感じていたところでした。
そこで今回は Next.js でのSSGを試していこうかなと思います。

余談ですが、SSGでいうと Astro なんかも聞くことがありますね。今後こちらも検証していきたいなと考えております。

実際に試していく

Next.js でのプロジェクト作成をしていきます。お馴染みすぎるコマンドです。
https://nextjs.org/docs/pages/api-reference/create-next-app

$ npx create-next-app@latest

SSGの設定

ビルド時に静的なページを生成するようにするには、config を書き換えてあげるだけでできてしまうようです。
next.config.js ファイル もしくは next.config.mjs ファイルに設定を書き加えることで実現します。
next.config.mjs ファイルを例にします。 output というパラメータを追加するだけです。

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  // ↓ ここを追加
  output: 'export',
  // SSGではnext/imageが利用できない。今回はunoptimizedで割愛
  images: {
    unoptimized: true,
  }
};

export default nextConfig;

また、画像のoptimizedの設定を無効化するようにしています。SSGの際には next/image をそのまま利用することができません。Loaderというものを設定することで最適化をはかることができますが、今回は割愛させていただきます。

ビルドしてみる

プロジェクトを作成した状態から、実際にビルドコマンドを実行してみます。

$ npm run build

すると out というディレクトリに生成されたファイルが含まれていることを確認することができるかと思います。

npx http-server

静的ファイルのサーバーを立ち上げるのに便利な http-server などを利用して確認すると、お馴染みの Next.js のホーム画面が開かれるのではと思います。

外部のデータと連携したページを作成する

SSGでのサイト作成では、Headless CMS のようなコンテンツ管理のサービスなどを利用するパターンが存在するかと思います。API経由でデータを取得し、そのデータをもって静的ファイルを生成するような段取りです。

こちらは Next.js で標準として存在する getStaticProps というasyncなfunctionを実行することで実現することができます。
https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation
pages ディレクトリ配下にexternal.tsx というファイルを作成して、動的なコンテンツを取得してページを生成するようにしたいと思います。

import { InferGetStaticPropsType, NextPage } from "next"

type PageProps = InferGetStaticPropsType<typeof getStaticProps>;
const External: NextPage<PageProps> = (props: PageProps) => {
  return (
    <div>
      <h1>{props.title}</h1>
    </div>
  )

}

export const getStaticProps = async () => {
  // ここにAPI経由でデータを取得するようなロジックを記載するイメージ
  return {
    props: {
      title: 'External'
    }
  }
}

export default External

getStaticProps というメソッドがビルド時に実行されるメソッドになります。
ビルドして確認した結果… コンテンツが生成されていることが確認できるかと思います。実際には非同期でデータを取得するようなロジックが記載されることになるかと思いますが、こちらも今回は割愛いたします。

ページを動的に作成する

上記のように、コンテンツ管理のサービスでSSGを利用する場合はページのパスを動的に生成する必要があります。コラムページのような同じ構成のページが複数できるようなイメージです。
こちらもNext.jsが標準で搭載している getStaticPaths を利用することで実現することができます。
pages ディレクトリに [id].tsx というファイルを作成して、動的にページを生成するようにしたいと思います。

import { GetStaticProps, GetStaticPropsContext, InferGetStaticPropsType, NextPage } from "next"

type PageProps = InferGetStaticPropsType<typeof getStaticProps>;
const External: NextPage<PageProps> = (props: PageProps) => {
  return (
    <div>
      <h1>{props.title}ですよ〜</h1>
    </div>
  )

}

export const getStaticPaths = async () => {
  // 動的に作成する対象のページの元となる部分
  return {
    paths: [
      { params: { id: '1' } },
      { params: { id: '2' } },
    ],
    fallback: false
  }
}

export const getStaticProps: GetStaticProps = async ({params}: GetStaticPropsContext) => {
  return {
    props: {
      title: params?.id?.toString()
    }
  }
}

export default External

getStaticPaths というメソッドで生成されるページの値を返します。
また getStaticProps では、上記のメソッドを受け取ることができるため。
一覧用のAPIを実行する一覧から取得したidを元に詳細のAPIを実行する といった流れでデータ取得をすることが可能になります。


とんでもなく簡素ですが、ページが生成されたことが確認できました。

実際にやってみた感想

実装をする前は、「SSGの設定って結構大変なんじゃないかな」と思っていたのですがかなり容易に実現することができ驚きでした。
今回触れなかった部分でいうと、

  • 現在 Gatsby.js で運用しているLPでも利用している microCMS との連携
  • 多言語化の対応
    などがあげられます。特に多言語化に関してはURLベースで翻訳結果を変えるみたいなことが必要になるはずであるためハマりどころになるんじゃないかな〜と勝手に思っていたりします。
    AstroでのSSGも書けたら書こうと思います。たぶん。
    ここまでご覧いただきありがとうございました!
アルダグラム Tech Blog

Discussion