Pre-rendering in Next.js
Two forms of Pre-rendering in Next.js
By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO.
NextJS gives us two forms of pre-rendering, which we can use for controlling how the pages should be rendered. It has something which is called Static Generation and it has an alternative, which is called Server-side Rendering. And the two might sound similar but they run or the code runs at different points in time as you will see in the video above.
Static Generation
That is the approach that you typically should use. When using Static Generation, a page component is pre-rendered when you build your NextJs project (when you build it for production).
npm run build
With Static Generation, by default, your page is not pre-rendered on the fly on the server when a request reaches the server, but instead, it is pre-rendered when you as a developer build your site for production. And that means that after it was deployed, that pre-rendered page does not change. At least not by default.
If you then updated the data, and you know that the pre-rendered page needs to change, you need to start that build process and redeploy again.
NextJS prepares your pages. It by default generates your pages, already statically, and it by default does that during the build process. But if you need to wait for data, if you need to add data fetching to a page component, you can do so by exporting a special function from inside your page component file.
getStaticProps
export async function getStaticProps() { // fetch data from an API return { props: { meetups:DUMMY_ITEMS }, }; }
NextJS first of all, calls getStaticProps before it calls the component function. And getStaticProps has this name because indeed, its job is to prepare props for this page. And these props could then contain the data this page needs. And that’s useful because getStaticProps is allowed to be asynchronous. You can return a promise there and then, and that’s the key thing, NextJS will wait for this promise to resolve. This means it waits until your data is loaded and then you return the props for this component function.
If we then add more items to our database, this pre-generated page by Next.js would not know about them. And if we don’t add any client-side data fetching, we would always just see the outdated items here. And this could, of course, be a problem.
Now, we can always rebuild our site and redeploy when our data changes. And for some websites, like personal blogs, this is a great alternative because their data doesn’t change too frequently, but if data does change more frequently, there is an extra property (revalidate), which we can add to this returned object.
revalidate
export async function getStaticProps() {
// fetch data form an API
return {
props: { items: DUMMY_ITEMS }, revalidate: 15
};
}
When we add this property to the object returned by getStaticProps, we unlock a feature called incremental Static Generation. Revalidate property wants a number, let’s say 15, and this number is the number of seconds NextJS will wait until it regenerates this page for an incoming request.
That means that with revalidate property set to some number, this page will not just be generated during the build process. It will be generated there but not just, but it will also be generated every couple of seconds on the server, at least if there are requests for this page.
So that means that this page, with revalidate set to 15, would be regenerated on the server at least every 15 seconds if requests are coming in for this page. And then these regenerated pages would replace the old pre-generated pages.
And with that, you would ensure that your data is never older than 15 seconds. And therefore, the number of seconds you wanna use here depends on your data update frequency. If your data changes once every hour, then setting this to 3600 might be great.
But whatever you set this number, you will ensure that this page will occasionally be re-generated on the server after deployment so that you don’t have to redeploy and rebuild all the time just because some data changed.
Server-side Rendering
So getStaticProps is a very useful function that you can export in your page components to ensure that your pre-rendered pages contain data you might need to wait for. Now with revalidate property, you can ensure that this page is also updated regularly after deployment. But sometimes even a regular update is not enough.
Sometimes you want to regenerate this page for every incoming request. So you want to pre-generate the page dynamically on the fly after deployment on the server. Not during the build process, and not every couple of seconds, but for every request. And if that’s your goal, then there is an alternative to getStaticProps.
And that’s the getServerSideProps function. Just like getStaticProps, that is a reserved name, that NextJS will be looking for. And the difference to getStaticProps is that this function will now not run during the build process, but instead always on the server after deployment.
getServerSideProps
export async function getServerSideProps(context) { const req = context.req; const res = context.res; // fetch data from an API return { props: { meetups:DUMMY_ITEMS } }; }
Any code you write here will always run on the server, never on the client. So you can run the server-side code here, you can also perform operations that use credentials that should not be exposed to your users because this code only runs on the server.
There is another method that we have already talked about in another post, getInitialProps. This method will be executed on the server during the initial page load and will be executed later in the browser if you transition client-side to other parts of the application. In this post we mentioned, we talked about a NextJS application deployed in a Kubernetes environment. But that’s another topic.
This getServerSideProps function runs for every incoming request.
We can see that in this method there is a parameter. In this context parameter (in this case, we don’t use it at all, we just show it. We could use it for authentication for example), you get access to the request object under the direct key, and the response object will be sent back. And if you worked with NodeJS and Express before, this might look familiar to you. There, you also get request and response objects in your middleware to then work with those.
Which form of pre-rendering in Next.js is better?
Is getServerSideProps better or getStaticProps?
getServerSideProps might sound better because it’s guaranteed to run for every request. But that actually can be a disadvantage, because that means that you need to wait for your page to be generated on every incoming request.
Now, if you don’t have data that changes all the time, and with that, I mean that it changes multiple times every second, and if you don’t need access to the request object, let’s say for authentication, getStaticProps is better. Because there you pre-generate an HTML file, that file can then be stored and served by a CDN. And that simply is faster than regenerating and fetching that data for every incoming request. So your page will be faster when working with getStaticProps, because then it can be cached and reused, instead of regenerated all the time.
Hence, you should only use getServerSideProps if you need access to that concrete request object because you don’t have access to request and response in getStaticProps. Or if you have data that changes multiple times every second, then therefore even Revalidate property won’t help you, then getServerSideProps is a great choice.
Leave a Reply
Want to join the discussion?Feel free to contribute!