I have noticed that the concept of pre-rendering, SSR and SSG is not very clear to many developers.
So let’s do some clarity them using React and NextJS and some animations I have created.
Pre-rendering: React vs NextJS
Lest’ start with the concept of pre-rendering.
In React and in SPAs in general, you usually have a single HTML page for the whole application and routes are “simulated” by destroying and creating components.
Your data are often acquired via REST API (or e.g. Graph QL) on the client side with a simple fetch when the component is initialized. For example, in React by using the useEffect hook, in Angular by using the ngOnInit lifecycle method and so on.
However, in this way, you will obtain a first render of the page without data that will be displayed only at the second render.
The result is superfluous rendering (so bad performance), longer loading times and very poor search engine results.
NextJS, on the other hand, pre-renders each page.
What does it mean?
Next, behind the scenes, uses several strategies to generate a different html for each single page of your app/website that already contain all data you need in the (first) render.
Each page can have its own title, metadata and is associated with the minimum JS code needed to make that page work.
This is automatically translates into better performance and SEO.
Hydration
When the page is loaded in the browser, a non-interactive version is first rendered, then the JS code necessary to make it work is loaded and finally the page becomes interactive.
This process is called Hydration.
SSR vs SSG
What I love about NextJS is the simplicity, compared to any other framework, with which it is possible to take advantage of the pre-rendering.
As I said earlier, React applications that need data acquired from external APIs usually have a first empty render, with no data, and then a second render in which the data is present.
This behavior can generate performance and SEO problems!
Thanks to the pre-rendering (done by NextJS) we can instead render a page that already contains data at the first render.
Next offers three pre-rendering modes in order to optimize site performance and search engine optimization: Server Side Rendering (SSR), Static Site Generation (SSG) and Incremental Static Regeneration (ISR).
In the animation above we see the differences between SSG and SSR.
1. SSG: pages are created at build time. When users request one of these pages NextJS provide a cached version where all data has been previously loaded and rendered on the page.
2. SSR: users request a page, NextJS fetch data behind the scenes, and the page is loaded.
Mixing SSR and SSG
Next offers the possibility to choose the pre-rendering method for each individual page.
It will then be possible to create Next hybrid applications that use SSG for some pages and SSR for others.
It is highly preferable to use SSG whenever possible. The applications will turn out really fast, as if “they were written in vanilla HTML / CSS”.
Sometimes you get the feeling of viewing a local site from your PC for how fast they are.
SSG with and without Data
When we create pages that do not require external data Next creates a static version of the page at build time (essentially HTML, CSS and the minimum JS code necessary to make it eventually interactive).
These pages act like normal React pages without pre-rendering in which it is still possible to make REST calls on the client side (i.e. by using useEffect hook and fetch API)
In many scenarios, however, we need to load data from external APIs, databases or even from local JSON and Markdown files. In this case Next will be able to make these requests during the build phase, acquiring the data and generating the static pages that already include all the data a page needs in the first render.
When data changes we have 3 ways to render the updates:
- a new build
- re-deploy
- use Incremental Site Regeneration (I’ll talk about this topic in another article)
Server Side Rendering (SSG)
Server side rendering comes to our aid if, on the other hand, we need to acquire data at each user’s request. NextJS takes care of each user request, acquires the data from an external source and renders the page on the fly.
It can be very useful when data changes frequently but server-side costs could increase dramatically over time. Furthermore, if we use third-party APIs that have a cost based on consumption (YouTube, Google Map, Firebase API and so on) these costs could also increase.
Conclusion
I hope this article has clarified some aspects which I had a hard time understanding at first and I apologize for my English, but most of my content has usually been written in Italian.
Let me know if you liked the article and if you are interested in other content like this on the technologies I love: Angular, React, Redux, NGRx, Next, RxJS or JS / TS