コンテンツにスキップ

静的サイト生成 (SSG)

静的生成を使用するページでは、ページHTMLはビルド時に生成されます。これは、本番環境ではnext buildを実行したときにページHTMLが生成されることを意味します。このHTMLは、リクエストごとに再利用されます。CDNでキャッシュできます。

Next.jsでは、データあり、またはデータなしでページを静的に生成できます。それぞれのケースを見ていきましょう。

データなしの静的生成

デフォルトでは、Next.jsはデータを取得せずに静的生成を使用してページをプリレンダリングします。以下に例を示します。

function About() {
  return <div>About</div>
}
 
export default About

このページは、プリレンダリングするために外部データを取得する必要がないことに注意してください。このような場合、Next.jsはビルド時にページごとに1つのHTMLファイルを生成します。

データありの静的生成

一部のページでは、プリレンダリングのために外部データを取得する必要があります。2つのシナリオがあり、1つまたは両方が適用される場合があります。各ケースで、Next.jsが提供するこれらの関数を使用できます。

  1. ページのコンテンツが外部データに依存する場合:getStaticPropsを使用します。
  2. ページのパスが外部データに依存する場合:getStaticPathsを使用します(通常はgetStaticPropsと併用)。

シナリオ1:ページの内容が外部データに依存する場合

:ブログページはCMS(コンテンツ管理システム)からブログ投稿のリストを取得する必要があるかもしれません。

// TODO: Need to fetch `posts` (by calling some API endpoint)
//       before this page can be pre-rendered.
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

プリレンダリングでこのデータを取得するために、Next.jsは同じファイルからgetStaticPropsという名前のasync関数をexportできるようにします。この関数はビルド時に呼び出され、取得したデータをプリレンダリング時のページのpropsに渡すことができます。

export default function Blog({ posts }) {
  // Render posts...
}
 
// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

getStaticPropsの機能の詳細については、Data Fetchingドキュメントを参照してください。

シナリオ2:ページのパスが外部データに依存する場合

Next.jsでは、動的ルートを持つページを作成できます。たとえば、pages/posts/[id].jsという名前のファイルを作成して、idに基づいて個々のブログ投稿を表示できます。これにより、posts/1にアクセスするとid: 1のブログ投稿が表示されます。

動的ルーティングの詳細については、Dynamic Routingドキュメントを参照してください。

ただし、ビルド時にプリレンダリングしたいidは、外部データに依存する場合があります。

:データベースに1つのブログ投稿(id: 1)のみを追加したとします。この場合、ビルド時にposts/1のみをプリレンダリングすることになります。

後で、id: 2の2番目の投稿を追加するかもしれません。その場合、posts/2もプリレンダリングすることになります。

したがって、プリレンダリングされるページのパスは外部データに依存します。これを処理するために、Next.jsでは動的ページ(この例ではpages/posts/[id].js)からgetStaticPathsという名前のasync関数をexportできます。この関数はビルド時に呼び出され、プリレンダリングしたいパスを指定できます。

// This function gets called at build time
export async function getStaticPaths() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
 
  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}

また、pages/posts/[id].jsgetStaticPropsexportして、そのidを持つ投稿に関するデータを取得し、ページをプリレンダリングするために使用する必要があります。

export default function Post({ post }) {
  // Render post...
}
 
export async function getStaticPaths() {
  // ...
}
 
// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()
 
  // Pass post data to the page via props
  return { props: { post } }
}

getStaticPathsの機能の詳細については、Data Fetchingドキュメントを参照してください。

静的生成はいつ使用すべきですか?

静的生成(データあり、なし両方)は、可能な限り使用することをお勧めします。なぜなら、ページは一度ビルドしてCDNで配信できるため、リクエストごとにサーバーがページをレンダリングするよりもはるかに高速だからです。

静的生成は、多くの種類のページに使用できます。例えば:

  • マーケティングページ
  • ブログ投稿やポートフォリオ
  • Eコマース商品のリスト
  • ヘルプとドキュメント

「ユーザーのリクエストの前にこのページをプリレンダリングできますか?」と自問してみてください。答えが「はい」なら、静的生成を選択すべきです。

一方、ユーザーのリクエストの前にページをプリレンダリングできない場合は、静的生成は適切ではありません。おそらく、ページは頻繁に更新されるデータを示しており、ページの内容はリクエストごとに変更されます。

このような場合は、次のいずれかを行います。

  • クライアントサイドデータ取得による静的生成:ページのいくつかの部分のプリレンダリングをスキップし、その後クライアントサイドJavaScriptを使用してそれらを populate できます。このアプローチの詳細については、Data Fetchingドキュメントを参照してください。
  • サーバーサイドレンダリングを使用する:Next.jsはリクエストごとにページをプリレンダリングします。CDNでページをキャッシュできないため遅くなりますが、プリレンダリングされたページは常に最新の状態になります。このアプローチについては、後述します。