What happened to getInitialProps

Remember getInitialProps?

Next.js has become more and more flexible over time.

Originally, getInitialProps was the only native data fetching method in Next.js.

Now, we've got:

  • getStaticProps
  • getStaticPaths
  • getServerSideProps

So why did Next.js add these new methods, and why is getInitialProps not used as frequently anymore? Let's look at some of the reasons.

How does getInitialProps work?

On the server

On the initial request, getInitialProps is called on the server. This data is used to populate the server-side rendered document. Developers would assume it's safe to make API calls using API keys, call secure endpoints, and read from environment variables here, though that's largely not the case.

On the client

Why? Because as soon as the client takes over, getInitialProps will be called when you navigate to a new page. This code runs in the browser, meaning you wouldn't want to ship secrets to make those same API calls.

Example

Page.getInitialProps = async (ctx) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const json = await res.json()
  return { stars: json.stargazers_count }
}

No harm here, right? This can run on both the server and the client without issue.

But what if we call an API that requires an API key?

const isServer = typeof window === 'undefined'

Page.getInitialProps = async (ctx) => {
  if (isServer) {
    const res = await fetch('https://example.com/secret-api-call', {
      headers: {
        Authorization: `Bearer ${process.env.SECRET_API_KEY}`
      }
    })
    const json = await res.json()
    return { data: json.secret }
  } else {
    return { data: 'Not safe to call on the client' }
  }
}

Do we see any problems here? The answer is yes. Our SECRET_API_KEY will be leaked to the client in this case.

This also leads to performance issues. If we include server-only modules not meant for the client, we can end up shipping massive JS bundles for no reason.

getInitialProps is a Swiss Army Knife of Next.js data fetching. Instead of being a generalist, let's reach for the right tool for the job.

What to do instead?

If you're using getInitialProps, what's your path forward? If you needed server-side rendering, what are the options?

Introducing getStaticProps & getStaticPaths

First things first, let's verify that you need server-side rendering. Lots of applications think SSR is required, but it's not. What's the alternative? Static rendering.

In Next.js, you can use getStaticProps and getStaticPaths to render static parts of your app.

  • getStaticPaths is used to generate a list of pages that your app should serve.
  • getStaticProps is used to fetch data for that specific page.

While this isn't a great metaphor, think of getStaticPaths as creating a bunch of buckets for your app to fill. getStaticProps is called for each bucket, and you can use it to fill that bucket with specific data it needs.

Consider a company's blog as an example of a type of page that works great for static generation. You want to generate a list of all the blog posts and fetch the content for each blog post.

In this case, getStaticPaths would return a list of all the blog posts, and getStaticProps would return the content for each blog post.

But what if the content in the CMS changes?

Perfect, you discovered the use case Incremental Static Regeneration (ISR).

Instead of generating all the pages and fetching content at build time, you can fetch it at runtime.

Incremental Static Regeneration (ISR) chart

Use the getStaticPaths function, but specify a revalidate parameter to tell Next.js to re-generate the page when the data changes and the time expires.

This is a common pattern in web development called stale-while-revalidate.

We immediately serve the stale page to the user and update it with the new data as it's ready.

Really need SSR? getServerSideProps is your friend

If you're confident that you need SSR and that ISR will not work for you, you can use getServerSideProps to fetch data for the server-side rendered page.

This will be called for each incoming request, and you can use it to fetch data for the server-side rendered page.

If using this approach, I'd recommend you set some caching headers on the response, so you're not burning through serverless compute time.

Do I have to upgrade?

The quick answer: no. Next.js has phenomenal backward compatibility across versions. Are there still valid use cases for getInitialProps? 100% yes. There are cases where grabbing Swiss Army Knife makes sense and cases where getInitialProps is a good fit.

Best of luck building your Next.js app!


See you on the other side,

Drew

Stay up to date

Don't miss my next essay — get it delivered straight to your inbox.

Related Content