SSR generates HTML on the server at each request, while SSG pre-renders pages at build time. This results in SSR being more suitable for frequently updated data and SSG for static content.
Key takeaways:
Server-side rendering (SSR) renders pages on the server at each request, while static site generation (SSG) pre-renders pages at build time, providing static HTML.
SSR is ideal for applications requiring frequently updated data or personalized experiences ensuring that users always see up-to-date content, making SSR a good fit for applications like dashboards, social media feeds, or news updates that rely on dynamic data.
SSG offers pre-rendered static pages, resulting in faster load times and reduced server load.
In Next.js, server-side rendering (SSR) is a process where the server generates HTML content on each request. This means every time a user or
Here is how SSR works:
User requests a site: The user sends a request to the server for a specific page.
Server creates ready HTML file: The server fetches necessary data, renders the HTML with that data, and sends the fully rendered HTML page back to the browser.
Browser renders HTML: The browser displays the HTML content immediately. At this stage, the page is fully rendered, but it is not yet interactive.
Browser downloads JS: The browser then downloads the JavaScript files necessary for the page.
Browser executes JS: Once the JavaScript is downloaded, the browser executes it. This process is often referred to as
Website is fully interactive: After the JavaScript is executed, the website is now fully interactive, and the user can interact with the page as expected.
Excellent for SEO: Since the entire page is rendered server-side, web crawlers can easily index the site, boosting your SEO performance.
Frequently updated data: SSR is ideal for applications that require fresh data on every request, such as e-commerce sites or news platforms.
Get hands-on experence with SSR with our Build a Multi-Tenant E-Commerce App with Next.js and Firebase project.
Increased time to first nyte (TTFB): Generating the HTML for each request can lead to delays before the page is visible to the user, especially under high traffic.
Higher server load: Every request generates a new HTML page, increasing the server load and potentially requiring more resources.
The getServerSideProps
function in Next.js is an SSR method that enables data fetching on each request. This means the data is retrieved, and the page is rendered on the server before being sent to the client. Let's look at an example of this:
import React from 'react'; // Used to simulate dynamic data function getRandomUser() { const users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Doe', email: 'jane@example.com' }, { id: 3, name: 'Alice Smith', email: 'alice@example.com' }, { id: 4, name: 'Bob Johnson', email: 'bob@example.com' }, ]; return users[Math.floor(Math.random() * users.length)]; } export async function getServerSideProps() { // Simulate dynamic data generation const randomUser = getRandomUser(); return { props: { randomUser, } }; } function SSRPage({ randomUser }) { // Render data... return ( <div> <h1>Sample Data:</h1> <pre>{JSON.stringify(randomUser, null, 2)}</pre> </div> ); } export default SSRPage;
Lines 4–12: We define a function getRandomUser
, which simulates dynamic data generation by selecting a random user from a predefined list of users. Each user has an id
, name
, and email
.
Lines 14–23: We define the getServerSideProps
function, which runs on the server for every request. This function calls getRandomUser
to retrieve a random user object.
Lines 25–33: The SSRPage
component receives the randomUser
prop and renders the user data in a JSON format within a <pre>
tag for easy readability.
SSR is suitable for applications requiring frequently updated data, personalization, or SEO optimization.
It is ideal for pages with frequently changing content or user-specific data.
Static site generation (SSG) involves generating the HTML pages at build time, meaning the server generates the HTML once and uses the same HTML for every request. This technique is beneficial when dealing with sites where content changes infrequently.
Here is how SSG works:
User requests a site: The user’s browser sends a request to the server for a specific page.
Server sends pre-built static HTML file with JS resources: The server responds with a pre-rendered static HTML file, which is generated at build time, along with any required JavaScript and CSS files.
Browser renders HTML and downloads JS: The browser immediately renders the static HTML content. Simultaneously, it starts downloading the linked JavaScript files.
User sees the fully rendered static page: The user immediately sees a fully rendered static page because the HTML is pre-generated. However, at this point, the page might not be interactive (e.g., buttons might not work, or dynamic content might not update).
Browser executes JS and hydrates the page: After the JavaScript files are downloaded, the browser executes them. Via hydration
Website is fully interactive: After hydration, the static page becomes fully interactive. Now, the user can interact with dynamic elements like forms, buttons, and other interactive features.
Fast loading times: Pre-generated HTML files are served instantly, resulting in quicker page loads.
Lower server load: Since the server doesn’t need to generate a page for each request, it can handle more traffic efficiently.
Try out this project, Build a Digital Library Using Gatsby and GraphQL for hands-on SSG experience.
Build time: For sites with thousands of pages, the build process can be time-consuming.
Data freshness: Content changes require rebuilding the site, which can be cumbersome for frequently updated sites. However, using Incremental Static Regeneration (ISR) can mitigate this issue.
The getStaticProps
function is used to generate static pages at build time. It runs only on the server during the build process. Let's look at an example of this:
import React from 'react'; // Used to simulate dynamic data function getRandomUser() { const users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Doe', email: 'jane@example.com' }, { id: 3, name: 'Alice Smith', email: 'alice@example.com' }, { id: 4, name: 'Bob Johnson', email: 'bob@example.com' }, ]; return users[Math.floor(Math.random() * users.length)]; } export async function getStaticProps() { // Simulate dynamic data generation const randomUser = getRandomUser(); return { props: { randomUser, } }; } function SSGPage({ randomUser }) { // Render data... return ( <div> <h1>Sample Data:</h1> <pre>{JSON.stringify(randomUser, null, 2)}</pre> </div> ); } export default SSGPage;
Lines 4–12: We define a function getRandomUser
, which simulates dynamic data generation by selecting a random user from a predefined list of users. Each user has an id
, name
, and email
.
Lines 14–23: We define the getStaticProps
function, which runs at build time to generate static content. This function calls getRandomUser
to retrieve a random user object.
Lines 25–33: The SSGPage
component receives the randomUser
prop and renders the user data in a JSON format within a <pre>
tag for easy readability.
SSG is suitable for content-heavy websites, blogs, and marketing pages with relatively static content.
It is ideal for sites that don't require frequently updated data updates for every user visit.
Learn more about rendering strategies in Next.js with this blog: Understanding Rendering in Next.js.
Let's now look at a comparison table for SSR vs. SSG in Next.js:
SSR | SSG | |
Rendering time | The HTML is generated on-the-fly at the time of each request by the server. | The HTML is generated at build time and reused for each request. |
Performance | Each request results in a round-trip to the server, which could lead to longer loading times compared to SSG, especially if the server is under heavy load or the user has a slow internet connection. | As the page is pre-rendered and can be served from a Content Delivery Network (CDN), it typically loads faster than SSR. |
Fequently updated data | Suitable for pages that need to display frequently updated data, as the content is refreshed on each request from the server. | Not suitable for displaying frequently updated data, as the content is static and only updated at build time. |
Server load | Every request to the server generates a new HTML page, which could put a heavier load on the server. | Lower server load as the HTML is generated only once at build time and served statically for each subsequent request. |
Development complexity | Typically requires a server or serverless functions to generate the HTML for each request. It might add a level of complexity depending on the project's architecture. | Usually simpler because the HTML is pre-generated. The deployment can be as simple as hosting static files on a CDN. |
The choice between SSR and SSG depends largely on your application’s specific requirements:
Using SSR: If your page needs to be updated frequently, requires frequently updated data, or needs to be personalized for individual users. E-commerce sites or social media platforms could be examples where SSR might be preferable.
Using SSG: When your page can be pre-rendered ahead of a user’s request. This is often the case for blog posts, marketing pages, or documentation, where content changes infrequently and doesn’t require user-specific data on every request.
Explore these projects for hands-on practice:
Haven’t found what you were looking for? Contact Us
Free Resources