Static Site Generation (SSG) Deep Dive

Deep Dive into Static Site Generation (SSG) and Incremental Static Regeneration (ISR)
What is Static Generation?
Static Generation (SSG) means that Next.js pre-renders pages at build time.
The output is a set of static HTML files that can be cached by the server or CDN, ensuring fast loading and SEO friendliness.
How It Works
- During
npm run build, Next.js executes your page’sgetStaticProps()function. - The function fetches and prepares data on the server side, before deployment.
- Next.js builds static HTML + JSON for each page and stores them for direct serving.
getStaticProps() — Build-time Data Fetching
This function runs only on the server, and only at build time.
It never executes in the browser.
export async function getStaticProps() { return { props: { products: [{ id: "p1", title: "Product 1" }], }, }; }
The object returned by getStaticProps() must include:
- props: Data passed to the page component.
- (optional) revalidate: Enables Incremental Static Regeneration.
export async function getStaticProps() { console.log("regenerating..."); const filePath = path.join(process.cwd(), 'data', 'dummy-backend.json'); const jsonData = await fs.readFile(filePath); const data = JSON.parse(jsonData); return { props: { products: data.products, }, revalidate: 20, // Enable ISR }; }
Why revalidate Matters?
Without ISR, the page is generated once at build time — it never updates until you rebuild. ISR solves this by allowing automatic regeneration after deployment.
- revalidate: 20 → If more than 20 seconds have passed since the last generation, Next.js re-runs getStaticProps() on the server to rebuild the page in the background.
- The new version replaces the old static HTML once ready.
- This keeps performance high while ensuring data freshness.
Note: revalidate works only in production (npm run build && npm start), not in development mode (npm run dev).
getStaticPaths() — Pre-Rendering Dynamic Routes
For dynamic pages like /products/[pid].js, Next.js needs to know which paths to pre-render.
async function getData() { const filePath = path.join(process.cwd(), 'data', 'dummy-backend.json'); const jsonData = await fs.readFile(filePath); return JSON.parse(jsonData); } export async function getStaticPaths() { const data = await getData(); const ids = data.products.map(product => product.id); const pathsWithParams = ids.map(id => ({ params: { pid: id } })); return { paths: pathsWithParams, fallback: 'blocking', // or 'true' / 'false' }; }
Understanding fallback Options:
- false: Only pages returned by getStaticPaths() are pre-rendered. Any other path → 404.
- true: Unlisted paths initially show a loading state (CSR) while the server generates and caches the new page.
- 'blocking': Requests for new paths wait until the server generates the HTML, then return the fully rendered page (no loading state).