Static Site Generation (SSG)
ページが Static Generation を使用する場合、ページのHTMLはビルド時に生成される。
つまり、運用環境では、next build を実行するときにページのHTMLが生成される。
このHTMLはリクエストごとに再利用される。
CDNによってキャッシュされることもある。
Next.jsでは、データの有無にかかわらず、静的にページを生成することができる。
Static Generation without data
デフォルトでは、Next.jsはデータをフェッチせずに Static Generation を使ってページをプリレンダリングする。
function About() {
return <div>About</div>
}
export default About
このページは、プリレンダリングするために外部データをフェッチする必要がない。
このような場合、Next.jsはビルド時に1ページにつき1つのHTMLファイルを生成する。
Static Generation with data
ページによっては、プリレンダリングのために外部データを取得する必要がある。
2つのシナリオがあり、どちらか、あるいは両方が当てはまるかもしれない。
いずれの場合も、Next.jsが提供するこれらの関数を使用できる。
Scenario 1: Your page content depends on external data(getStaticProps)
例: あなたのブログページは、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という非同期関数をエクスポートできる。
この関数はビルド時に呼び出され、
プリレンダリング時に取得したデータをページの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のドキュメントを参照。
Scenario 2: Your page paths depend on external data(getStaticPaths)
Next.jsでは、動的なルートを持つページを作成することができる。
たとえば、pages/posts/[id].jsというファイルを作成して、
idに基づいた単一のブログ記事を表示することができる。
これにより、posts/1にアクセスしたときにid: 1のブログ記事を表示することができる。
しかし、ビルド時にどのidをプリレンダリングするかは、
外部データに依存するかもしれない。
例えば、ブログ記事(id: 1)を1つだけデータベースに追加したとする。
この場合、ビルド時にposts/1をプリレンダリングしたいだけ。
その後、2番目の投稿をid: 2で追加することになる。
そのため、プリレンダリングされるページパスは外部データに依存する。
これを処理するために、Next.jsでは動的ページ(この場合はpages/posts/[id].js)からgetStaticPathsという非同期関数をエクスポートできる。
この関数はビルド時に呼び出され、プリレンダリングしたいパスを指定できる。
// 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 } }
}
When should I use Static Generation?
私たちは、可能な限り Static Generation(データあり、データなし)を使用することを推奨。
Static Generationは、次のようなさまざまなタイプのページに使用できる。
- マーケティングページ
- ブログ記事とポートフォリオ
- Eコマース商品リスト
- ヘルプとドキュメント
あなたは自問すべき。
"ユーザーのリクエストに先駆けて、このページをプリレンダリングできるか?"
もし答えがイエスなら、Static Generationを選ぶべき。
一方、Static Generation(静的生成)は、
ユーザーのリクエストに先立ってページをプリレンダリングできない場合には、
良いアイデアとは言えません。
例えば、あなたのページが頻繁に更新されるデータを表示していて、
リクエストのたびにページの内容が変わるような場合です。
このような場合、次のいずれかの方法をとることができる。
その1
クライアントサイドのデータ・フェッチでStatic Generationを使用する。
ページの一部のプリレンダリングをスキップして、
クライアントサイドのJavaScriptを使用してデータを入力することができる。
その2
サーバーサイド・レンダリングを使用する。
Next.jsはリクエストごとにページをプリレンダリングします。
CDNによってページがキャッシュされないので遅くなりますが、
プリレンダリングされたページは常に最新の状態になる。