VOOZH about

URL: https://blog.logrocket.com/ssg-vs-ssr-in-next-js/

⇱ SSG vs. SSR in Next.js - LogRocket Blog


2021-05-31
1307
#nextjs
Leonardo Maldonado
52058
👁 Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

🚀 Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

Introduction

Next.js is one of the most important and widely-used React frameworks. Today, it has become a consolidated framework for building amazing web applications.

👁 Image

Many advantages can be listed when using Next.js. Performance, SEO, rich developer experience, TypeScript support, smart bundling, and route pre-fetching are just a few examples.

Besides all of the amazing features that Next.js has to offer, there’s one in particular that is very powerful and amazing: the ability to use different pre-rendering techniques.

We can work with server-side rendering (SSR) and static site generation (SSG) in the same Next.js application. We can also have our server-side rendered application and still have some generated pages inside.

In this article, we’re going to learn more about how these two pre-rendering techniques work and how we can use them. We’re also going to learn more about the specific use cases for both of them.

SSR (server-side rendering)

Modern JavaScript frameworks have made our lives as developers much easier. We can create powerful, rich web applications using many different rendering techniques.

You have probably heard of single page applications before. A single page application is an application that is rendered at the client side, even if the data might be fetched from the server.

Server-side rendering (SSR) is the exact opposite of this. SSR describes the process of pre-rendering the page on the server, which is then generated upon each user request.

When the pre-rendered page reaches the browser, JavaScript code is run to make the page interactive. This whole process makes the load speed faster. It also makes it easier and preferable to use server-side rendering for applications that depend on SEO.

Next.js does this work out of the box. By default, it will try to detect which pre-rendering technique your application is using and fetch your data.

Years ago, before JavaScript became so mature and powerful, developers usually returned HTML files based on HTTP calls. It was a very common technique to process the response on the server side using a server-side language (usually PHP) and returning a static HTML file.

SSG (static site generation)

Static-generated websites are nothing new for developers. We have been building them since the beginning of the web. Building rich web experiences can be hard, but with Next.js we can do so easily.


Over 200k developers use LogRocket to create better digital experiences

👁 Image
Learn more →

Next.js has introduced us to a better way of building static-generated websites with more dynamic performance.

SSG describes the process of building websites that render at build time. The output is an HTML file, assets such as JavaScript and CSS, and a few other static files.

When using SSG with Next.js, the page is pre-rendered at compile time. That means that the user won’t have to wait for the page to load at the browser; the page will simply be rendered.

For data fetching, Next.js provides three different functions:

  • getStaticProps : The page will be pre-rendered at build time
  • getServerSideProps:  The page will be pre-rendered at runtime
  • getStaticPaths : This function generates a list of pages that will be pre-rendered at build time

The biggest disadvantage of using SSG is that the build time can get very long. You won’t have a problem when you have only a few statically-generated pages, but as your application grows, the build time will increase.

The worst case scenario is when you have hundreds of statically-generated pages. The build time will take a long time, and if you have dynamic content on those pages, you can end up with too many builds.

Which one should I use?

Next.js makes it really easy for us to pick the correct pre-rendering technique for each page.

Remember, we learned that Next.js does static site generation by default. It simply works out of the box. However, it will try to detect which pre-rendering method you’re using for each page.


More great articles from LogRocket:


There are definitely some cases in which choosing the right function for fetching your data will make a difference. It should be taken in consideration because it can cause a huge impact on the user experience.

Imagine that we are creating a simple blog website. The content will be totally statically-generated, right? We will have only a few pages and the content will be fetched from our server, so it makes total sense to go with SSG in this case.

We can assume that every blog has at least two essential pages:

  • posts : This page is responsible for fetching and displaying all the blog posts
  • post : This page is responsible for fetching and displaying a specific blog post

In our posts page, we can use SSG for fetching all of our blog posts, using the getStaticProps function:

export default function Posts({ posts }) {
 return (
 <div>
 <h1>My latest posts</h1>
 {posts.map((post) => (
 <h2>{post.title}</h2>
 ))}
 </div>
 );
}

export async function getStaticProps() {
 return {
 props: { 
 posts: await fetchPosts(),
 }
 };
}

The fetchPosts function will be run at build time. It will fetch our external data and pre render the content for our page.

Now, imagine that we want to add a little feature on our simple blog website.

Imagine that we’re a very famous person and our followers want to buy items from our store. We want to turn our simple blog website into an ecommerce application and start to sell items such as shirts, mugs, and stickers.

All the components that an ecommerce application contains can use the same pre-rendering technique. We can use the getStaticProps function for fetching our data at build time.

Now, what could we use for our checkout session? Every ecommerce application must have a checkout session where the user will conclude their purchase. In this case, the data can be fetched from our database at build time, but it can be different for each user.

We can use client-side fetching on top of SSG for rendering our page. We can create our simple component without using any function for fetching data at build time, and inside our component, we can use a data fetching library such as SWR for fetching our data on the client side:

import useSWR from "swr";
export default function CheckoutSession() {
 const { data, error } = useSWR("/api/checkout", fetcher)
 if (error) return <div>Something went wrong...</div>
 if (!data) return <div>Loading...</div>
 return <div>Cart: {data.items.length}</div>
}

Using server-side rendering with the getServerSideProps can do the job most of the time. The problem is that you might lose some features and advantages that SSG brings to Next.js applications. The page will be pre-rendered on each request using the data returned. Another disadvantage is that you can’t use a [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) method to call an API inside the getServerSideProps.

The fact that the page is pre-rendered at build time increases the performance and makes the page feel faster.

The HTML can also be fetched by a CDN server, which can also improve performance.

Another nice feature of SSG is that there’s no need to make a request to the database. The page is pre-rendered at build time, so even if your database goes down, you will still be able to render your page.

Conclusion

Next.js has become one of the most important React frameworks in the web community. It brought to developers so many features for helping to build more complex and rich websites.

Using a framework like Next.js allows us to use different pre-rendering techniques on our applications. We can use static site generation for something more simple and non dynamic. We can use server-side rendering for dynamic content and more complex pages. With these tools, building rich web applications has become easier and more fun.

LogRocket: Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket captures console logs, errors, network requests, and pixel-perfect DOM recordings from user sessions and lets you replay them as users saw it, eliminating guesswork around why bugs happen — compatible with all frameworks.

LogRocket's Galileo AI watches sessions for you, instantly identifying and explaining user struggles with automated monitoring of your entire product experience.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

👁 Image
👁 LogRocket Dashboard Free Trial Banner

Modernize how you debug your Next.js apps — start monitoring for free.

👁 Image
👁 Image
👁 Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension — no new framework required.

👁 Image
Ikeh Akinyemi
Jun 12, 2026 ⋅ 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo — with email/password login, Google OAuth, session persistence, and protected routes.

👁 Image
Chinwike Maduabuchi
Jun 9, 2026 ⋅ 13 min read

AI dev tool power rankings & comparison [June 2026]

Compare the top AI development tools and models of June 2026. View updated rankings, feature breakdowns, and find the best fit for you.

👁 Image
Chizaram Ken
Jun 8, 2026 ⋅ 11 min read

How to check username availability at scale with Bloom filters

Learn how Bloom filters reduce database lookups for username availability checks while preserving correctness at scale.

👁 Image
Rosario De Chiara
Jun 8, 2026 ⋅ 6 min read
View all posts

Hey there, want to help make our blog better?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now