Loading...
Loading...
SSG (Static Site Generation) is a rendering strategy where HTML pages are generated once at build time (next build). After deployment these pages are served as regular static files via CDN.
Next.js calls the server component or getStaticProps, runs all API/DB requests and generates HTML files for each page.
The ready HTML files are placed on a CDN. The server no longer participates in page generation.
When a user opens a page, the CDN instantly serves the ready HTML. No waiting for the server, no real-time rendering.
In the App Router (Next.js 13+) SSG is the default behavior. If a component does not use dynamic data, Next.js will automatically generate it statically:
// app/docs/page.tsx
// This page will be statically generated at build time
export default async function DocsPage() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return (
<ul>
{docs.map((doc: { slug: string; title: string }) => (
<li key={doc.slug}>{doc.title}</li>
))}
</ul>
)
}
By default fetch in server components caches the result. This is the equivalent of SSG: the request runs once at build time.
For dynamic pages you need to specify which paths to generate in advance. Use generateStaticParams for this:
// app/docs/[slug]/page.tsx
export async function generateStaticParams() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return docs.map((doc: { slug: string }) => ({
slug: doc.slug
}))
}
export default async function DocPage({
params
}: {
params: { slug: string }
}) {
const res = await fetch(
`https://api.hackfrontend.com/docs/${params.slug}`
)
const doc = await res.json()
return (
<article>
<h1>{doc.title}</h1>
<div>{doc.content}</div>
</article>
)
}
At build time Next.js calls generateStaticParams, gets the list of slugs and generates a separate HTML file for each.
In the Pages Router SSG uses getStaticProps:
// pages/docs/index.tsx
export async function getStaticProps() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return {
props: { docs }
}
}
export default function DocsPage({ docs }) {
return (
<ul>
{docs.map(doc => (
<li key={doc.slug}>{doc.title}</li>
))}
</ul>
)
}
For dynamic routes getStaticPaths is also needed:
// pages/docs/[slug].tsx
export async function getStaticPaths() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return {
paths: docs.map(doc => ({ params: { slug: doc.slug } })),
fallback: false
}
}
export async function getStaticProps({ params }) {
const res = await fetch(
`https://api.hackfrontend.com/docs/${params.slug}`
)
const doc = await res.json()
return { props: { doc } }
}
Good for:
Not suitable for:
Interview tip:
A common question: "What if the data becomes stale after the build?". Answer: that is what ISR (Incremental Static Regeneration) is for. It lets you update static pages without a full rebuild.