Flo Design Limited Logo

Static Site Generation in NextJS 9.3

Craig Thompson
Craig Thompson
  • #dev
  • #nextJs
  • #JAMstack

Here at FloDesign we've been using Next.js for the majority of our JAMStack sites. While we've tried other combinations of site generators and Content Management Systems (CMS), Next.js gives us flexibility in how we render and serve pages. Version 9.3 has brought even more goodies, in the form of build-time Static Site Generation (SSG).

Prior art

In version 9.0, Next gave us Automatic Static Optimisation. This allowed site creators to create pages without blocking data needs (pages using getInitialProps). When the site was built, these pages would be generated as static HTML pages. This allowed them to be served from a CDN with no server-side computation. Blistering-fast web pages written in the same framework and using the same components as your server & client-side rendered code. Noice!

Automatic Static Optimisation was a good step but it excluded pages with blocking data fetching needs where the content didn't change all that often. Even if the content hadn't changed for months, the server still had to fetch it from your data store, mash it together with your markup and fire it down the pipe to your user's browser. The data might be cached by your data store, speeding things up, but it was still a round trip that needed to be completed before the user saw your content

Enter SSG

Static Site Generation in Next.js allows us to handle these cases with dynamic, but rarely-changed, content using a couple of new methods, getStaticProps and getStaticPaths.

getStaticProps is a method for fetching data at build time. Consider a marketing page that is driven by a headless CMS.

// pages/marketing.js


// The marketing page component
const MyMarketingPage = ({page}) => (
	<>
		<h1>{page.title}</h1>
		<p>{page.content}</p>
	<>
);

export async function getStaticProps () {
	// Call our CMS to get the page content
	const response = await fetch('https://.../pages/marketing');

	// Send the data to our component as props.
	// We must return an object with the 'props' key
	return { props: response };
}

Run yarn build or npm run build and the framework will smush together your content and markup into speedy HTML.

Dynamic routes

On its own getStaticProps works well for single pages with dynamic content, like a marketing page or a blog listing page. However, we don't want to be creating page files in our code for every single one of our blog pages when we could use dynamic routes.

Thankfully, we can auto-generate those pages using a combination of getStaticProps and getStaticPaths.

// pages/blog/[slug].js

const Post = ({post)) => (
	// Render the post
);

export async function getStaticPaths() {
	// Get the list of posts from our API
  const res = await fetch('https://.../blog')
  const posts = await res.json()

	// Get an array of slugs to pass to getStaticProps
  const paths = posts.map(post => ({
    params: { slug: post.slug },
  }))

	// The slugs will be used to create paths and pre-render the posts
	// fallback: false means any paths not included in our params array will 404
  return { paths, fallback: false }
}

export async function getStaticProps({ params }) {
  // 'params' will contain the post slug for fetching from our API
  const res = await fetch(`https://.../blog/${params.slug}`)
  const post = await res.json()

  // Pass post data to the page via props
  return { props: { post } }
}

If we build our site now it will create our blog pages for us, from a single file!

Next.js now allows us to deal with all kinds of scenarios from the same codebase. The ability to mix content-driven pages, using data from a headless CMS, with static content and reactive, client-side rendering allows a huge amount of flexibility in how we develop for the web.

But what about....?

Before I'm accused of breathless adoration of this framework, I realise that JS tooling can be a bit like using a sledgehammer to crack a nut.

I agree completely. If you're situation requires only static content then write the site in HTML. You'll save yourself that extra 50-odd kB of Javascript, which won't be needed, alongside a ton of potential headaches with builds.

There are also other frameworks available (11ty, Gatsby, Hugo), which may suit your needs better. Try them out, and see what works for your circumstances. I'd love to hear your thoughts on which you think is best!