静的サイト生成 (SSG)
例
- WordPressの例(デモ)
- マークダウンファイルを使用したブログスターター (デモ)
- DatoCMSの例 (デモ)
- TakeShapeの例 (デモ)
- Sanityの例 (デモ)
- Prismicの例 (デモ)
- Contentful 例 (デモ)
- Strapi 例 (デモ)
- Prepr 例 (デモ)
- Agility CMS 例 (デモ)
- Cosmic 例 (デモ)
- ButterCMS 例 (デモ)
- Storyblok 例 (デモ)
- GraphCMS 例 (デモ)
- Kontent 例 (デモ)
- Builder.io 例 (デモ)
- TinaCMS 例 (デモ)
- 静的ツイート (デモ)
- Enterspeed 例 (デモ)
ページが**静的生成**を使用する場合、ページのHTMLは**ビルド時**に生成されます。つまり、本番環境では、`next build`を実行したときにページのHTMLが生成されます。このHTMLは、各リクエストで再利用されます。CDNによってキャッシュできます。
Next.jsでは、**データの有無にかかわらず**、ページを静的に生成できます。それぞれのケースを見てみましょう。
データなしの静的生成
デフォルトでは、Next.jsはデータの取得を行わずに、静的生成を使用してページを事前にレンダリングします。例を挙げます。
function About() {
return <div>About</div>
}
export default About
このページは、事前にレンダリングするために外部データを取得する必要がありません。このような場合、Next.jsはビルド時にページごとに単一のHTMLファイルを生成します。
データを含む静的生成
一部のページでは、事前にレンダリングするために外部データの取得が必要です。2つのシナリオがあり、どちらか一方、または両方が当てはまる場合があります。いずれの場合も、Next.jsが提供するこれらの関数を使用できます。
- ページの**コンテンツ**が外部データに依存する: `getStaticProps`を使用します。
- ページの**パス**が外部データに依存する: `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では、同じファイルから`async`関数である`getStaticProps`を`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`の動作の詳細については、データ取得ドキュメントを参照してください。
シナリオ2: ページのパスが外部データに依存する
Next.jsでは、**動的ルート**を持つページを作成できます。たとえば、`pages/posts/[id].js`というファイルを作成して、`id`に基づいて単一のブログ投稿を表示できます。これにより、`posts/1`にアクセスすると、`id: 1`のブログ投稿を表示できます。
動的ルーティングの詳細については、動的ルーティングドキュメントを参照してください。
しかし、ビルド時に事前にレンダリングする`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].js
では、getStaticProps
をエクスポートして、この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
の動作の詳細については、データフェッチングのドキュメントをご覧ください。
静的生成をいつ使用するべきですか?
可能な限り静的生成(データあり・なし両方)を使用することをお勧めします。ページを一度ビルドしてCDNで配信できるため、リクエストごとにサーバーでページをレンダリングするよりもはるかに高速です。
静的生成は、次のような多くのタイプのページに使用できます。
- マーケティングページ
- ブログ記事とポートフォリオ
- eコマースの商品一覧
- ヘルプとドキュメント
自問自答してください。「このページをユーザーのリクエストに先立って事前にレンダリングできますか?」答えが「はい」の場合、静的生成を選択する必要があります。
一方、ユーザーのリクエストに先立ってページを事前にレンダリングできない場合は、静的生成は適切ではありません。ページに頻繁に更新されるデータが表示され、ページの内容がリクエストごとに変化する可能性があります。
このような場合は、次のいずれかを実行できます。
- クライアントサイドのデータフェッチを使用した静的生成:ページの一部を事前にレンダリングせずにスキップし、クライアントサイドのJavaScriptを使用してそれらを埋め込むことができます。このアプローチの詳細については、データフェッチングのドキュメントをご覧ください。
- サーバーサイドレンダリングを使用する:Next.jsは、各リクエストでページを事前にレンダリングします。ページをCDNでキャッシュできないため速度は遅くなりますが、事前にレンダリングされたページは常に最新の状態になります。このアプローチについては、以下で説明します。
役に立ちましたか?