Explaining weird frontend terms - SSG, SSR, CSR and ISR and some history
Explains concepts like CSR, SSR, ISR and SSG in Next.js context
If you are a front end developer and are working on React, you must have heard about Next.js and its impressive rendering methods. Next.js is an advanced react framework with so many little things taken care of. One of the important features that is taken care of is the ability to Server side render the pages in the react application. In this article, let me explain the various rendering methods in Next.js and what to use when.
Client Side Rendering: (CSR)
Let’s start with the most simplest and most straight forward rendering approach available in React. It is Client side rendering. This approach takes the entire application and loads it into the client. Further requests and processing are then made by the client. This approach started with the introduction of Single Page Applications (SPAs) way back in 2008 and frameworks like Angular, React and Vue.
This was a radically new approach to rendering at that time. People were used to server side technologies like ASP.NET, Java Spring, Ruby on Rails and PHP. With this new approach, it felt like a breath of fresh air.
But what was the problem in server side?
Since there were so many frameworks ASP.NET, Java Spring, Ruby on Rails and PHP that used to render the page on the server and then send it to front-end, what was the problem there? There were quite a few:
- With traditional server-side rendering, the server responds by generating and returning a completely new page for every interaction. This often slows load time, uses more bandwidth, and creates a less responsive user experience. Client-side rendering avoids making unnecessary requests for a full page when only a portion of the page has changed
- Hosting an Angular application was much cheaper than hosting a full blown Java Server application. It reduced the complexity and provided the front end developer with more abilities in their arsenal. Deployment is also often very simple in a static application.
- Hate for existing frameworks and tools - during that time, everything about the backend was quite difficult. Writing a JSP application required tweaking and setting up so many configurations and it was quite difficult to manage. People were searching for a fresh alternative and a new approach to do things.
Enter Angular.js
During that time around 2008, Ryan Dahl introduced Node.js as a runtime for Javascript. Till that time, browsers like Chrome and Firefox were the only ones that could parse and execute Javascript code. With the introduction of Node.js , Ryan revolutionised the idea of executing Javascript in a backend environment. Although Node.js used Chrome’s v8 engine for parsing and executing Javascript, it was a much needed alternative.
Ryan Dahl
This triggered a series of javascript technologies to be released one after the other. One such interesting release is the release of Angular.js by Google. Interestingly, it started as a side project by one of the Googlers. They came up with the approach to switch the rendering from server side to client side in an increasing mobile based world. Angular.js became a huge success although it was needlessly complicated and had so many drawbacks. It had first class support for Client side rendering and abandoned server side rendering. Considered a welcome move at that time.
Due to the heavy drawbacks, many other frameworks like Ember.js, Meteor.js and eventually React.js by Facebook was also launched. It became an instant success and loved by millions worldwide.
But soon enough people started realising CSR has its own set of drawbacks. One of the major drawback is its hinderance in SEO and very high loading times for the site because it has to download the entire bundle from the server.
Server Side Rendering: (SSR)
To improve these drawbacks, alternative rendering approaches like SSR and SSG were developed. With SSR, all the rendering is done on the server at request-time. For every request, the server assembles the fetched data and HTML document and sends the client a complete document. The key thing to note here is the server builds and renders a new page for every request made.
SSR has grown in popularity in recent days due to the surge of JamStack apps and tools. Particularly Next.js and Vercel has made this idea popular and extremely easy to implement.
But isn’t this the same as server rendered pages like JSP?
Yes. Its just the same old server rendered pages but the advantage right now is, these SSR tools like Next.js utilise modern javascript frameworks and toolings. They also have a clear separation of concerns from the backend. This isn’t the typical server rendered pages like JSP or ASP.NET. Next.js still uses REST APIs to fetch the data to render from the backend service and then renders it during the build time of the front end application.
How to do SSR in Next.js?
Its easy. You just have to invoke the getServerSideProps() method like so:
export async function getServerSideProps(context) {
return {
// This props object will be passed to the page so they can be used on the frontend.
props: {},
}
}
But with SSR, since the page is rendered with custom data, each time a new request comes in, it is generally slower than SSG.
If you are mostly doing static sites, then ultimately its not worth it to do SSR.
Static Site Generation: (SSG)
SSG and SSR are nearly the same. The one big difference is that SSG does all of its rendering does it at build time and fully ready files are served from a CDN. SSG builds fetched data and HTML into a page once and then reuses the output from that build for all requests to that page until the next rebuild of the site.
It is the ultimate fastest way to render beautiful static sites using your favourite tools like React and Next.js. Since the pages are stored on a CDN, they are loaded extremely fast and are excellent for SEOs. Next.js recommends doing SSG whenever possible. It is better to try and avoid SSR in favour of SSG. They also provide other advantages like image optimisation, font optimisation, caching, etc.
Apart from Next.js, there are several SSG tools like Gatsby, etc.
How to do SSG in Next.js?
It is mostly the same as SSR except the name changes a bit.
export async function getStaticPaths() {
return {
// The paths to be pre-rendered at build time. E.g. /post/1, /post/2, etc
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
}
}
export async function getStaticProps(context) {
return {
// This props object will be passed to the page so they can be used on the frontend.
props: {},
}
}
But as with every approach, SSG has some drawbacks: The SSG pages are rendered on build time. Therefore, any updates to the content in the CMS (like Sanity) might have to wait for next rebuild of the frontend application to be reflected in the site.
Incremental Static Regeneration: (ISR)
But Next.js have already thought of this issue and have come up with the fix for it already. ISR addresses the one possible challenge with SSG, which is the need to rebuild your entire website to update a page’s content. With content updating frequently (e.g. on a blog), SSG might cause you to rebuild the entire site very frequently for changes that are contained in a single page. ISR allows you to rebuild only the updated pages after the site is built.
If you are running a blog site for example, there are 3 cases where this is useful:
- You have updated the existing content
- You have created a new article
- You have deleted an article
In Next.js, you have two key properties to perform ISR: revalidate and fallback
- revalidate - rebuilds the page for every given interval period.
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}
- fallback - constructs the url path by fetching from backend if it is not present
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// We'll pre-render only these paths at build time.
// { fallback: blocking } will server-render pages
// on-demand if the path doesn't exist.
return { paths, fallback: 'blocking' }
}
These two take care of the problems faced by SSG pages.
Verdict:
Use SSG with ISR all the time. That gives you enormous optimisation and performance boosts. If the application mandates custom data, go for SSR and at last consider CSR - for full fledged client side apps like a spreadsheet app, for example.
Thanks for reading :)