Understanding and Comparing SSR, ISR, and SSG in Nextjs
Strategies Next.js offers:
The first one is pre-rendering all pages during the build step and then sending them to the client. This is called static-site generation or SSG for short and it’s honestly a good solution if your application uses data that doesn’t change very often. But if it does, it is practically unusable. It’s called static for a reason.
So, what do you do when you have a dynamic application? You have several options. One of them is to simply rebuild the pages more often. If you have a blog, you might choose to trigger a new build every hour and that might be enough. This can be optimized by only triggering the build when a user visits your app and by only rebuilding the visited page. This system is called Incremental Static Regeneration or ISR because, in a way, your app regenerates.
However, there are a few drawbacks. The build is triggered when a user visits a page after a certain amount of time. But that user receives the old version of the app, with possibly stale data. And if the data is important, this is unacceptable. The other drawback is that you might end up with many pages which rebuild quite often, especially if you set the rebuild timer, also called cooldown, to only a few seconds.
In this case, you might as well use the third and final strategy Next.js has to offer. It's called server-side rendering, or SSR, and you are probably already familiar with it. When you use server-side rendering, Next renders your app and sends the HTML on each request. The biggest advantage of SSR is that users always have the latest data.
But this comes at a cost. It takes time to process the request and a lot of traffic can make the server quite busy.
Performance Difference in SSG, ISR, and SSR:
It should be quite clear that SSG (static-site generation) and ISR (incremental static regeneration) are going to be very fast because data fetching only happens once during the build. This allows the statically generated pages to be cached by CDNs to boost performance even more. With SSR (server-side rendering), data is fetched on each request. This results in a slight delay and if you want to always send the latest data, caching becomes quite complicated. But it is still faster than traditional client-side rendering. Finally, it is important to understand when the loaded page becomes interactive.
The process of making the page interactive is called hydration and it happens after the received HTML is painted. When you use pre-rendering, the painting happens very quickly and that’s what really separates it from client-side rendering.
Prerendering Content in Nextjs.
Imagine a page where you want to list your blog posts. If you want this page to be statically generated, you use a special method called getStaticProps, which gets called during the build process. All you have to do is fetch the posts, return them in props and then use them within the page. To turn this into incremental static regeneration, you simply add a Revalidate property with a time, for example, 60 seconds. This will tell Next to rebuild the page at most every 60 seconds. And if you need to use server-side rendering, you move the fetching code to a special method called getServerSideProps, which gets called during each page request.
So which approach is the best? That heavily depends on your use case. You should use static-site generation whenever you can, but often, it simply isn’t enough.
If you are fine with a few users receiving stale data, incremental static generation is the way. And whenever you need each user to have the latest data, use server-side rendering. But what if your application consists of pages with different needs? This is where Next truly shines. You can choose which form of pre-rendering you want for each page. In fact, it happens automatically based on the methods you use and by that, I mean the getStaticProps and getServerSideProps methods. This allows you to create hybrid performant applications where each page uses only what it needs. However, the benefits don’t end there.
If we go back to the blog example, you might wonder how we can generate a static page for each blog post. Next has a method called getStaticPaths that solves that very problem. In this method, you generate your paths and return them just like that. Another benefit is the Image component Next.js provides. It includes several built-in performance optimizations including lazy loading, serving different images for different devices, and many more. All of these are enabled by default.
Deploying Nextjs Application:
Now, let’s talk about deployment. The easiest way to deploy a Next.js application is to use the Vercel platform. It was created by the creators of Next itself and is designed specifically for it. When deploying your app using Vercel, it performs several optimizations including caching your assets, performing compression, and so on.
But running Next on your own isn’t difficult either because Next has been built at the top of Node.js, it can run on any Node server, so you can quite easily self-host your application by simply setting up a Node server. Next also has its own Docker image, so you can for example deploy it on Amazon Elastic Container Service or Amazon ECS for short.
So, should you use Next.js? The truth is that no matter what you are building, Next probably has you covered. Even if you aren’t interested in pre-rendering at all, you can choose to use good old client-side rendering.