What is Server-Side Rendering, Client-Side Rendering, Pre Rendering, Static sites, Universal applications, and where is the JAMstack between those
There are plenty of articles on this topic, but I still hear a lot of developers who have trouble understanding these techniques. Also, the situation is becoming more and more complex with the new tools, so I decided to write down my thoughts on this subject.
I’ll try to give a brief explanation one by one, highlighting the pros and cons, giving some examples, tools, and links to other articles to go deeper into some aspects. Hope to help others to choose with more awareness of what to do with your next project.
Introduction
Once upon a time, the web was simple (or simpler at least). Initially, the web was made just by HTML files, but with time passing by tools evolved (a lot), and the community created many solutions to make other developers’ life easier and to deliver sites with a better (and more complex) experience. The evolution naturally has initiated new approaches, so what was serving HTML files become building applications on the server (server-side rendered or pre-rendered), on the client (client-side rendered), or in both places (universal applications).
Some of the new things don’t have a great self-explanatory name (looking at you JAMstack) and so developers not catching up with new trends tend to be confused by all these names.
Server-Side Rendering (SSR)
This is the most ancient technique, not counting the simple host of static files (that actually is pre-rendering but we will come to that), and so it is easy to understand.
When a client opens a browser and requests a web page, the server builds the HTML response by populating it with all the necessary information (HTML tags, filled data fetched from a DB or somewhere else, the CSS, etc…). The response that the browser receives is a full HTML file, already filled with everything it needs.
This means that when the response reaches the browser, he just has to parse and render the response, not much else to do.
Italian style ELI5: you are a guy (browser) and you order a pepperoni pizza (request a page) from a pizzeria (server). If the pizza is server-side rendered you are going to receive a perfect pepperoni pizza like you asked from the delivery man, you just open it and eat it (show to the end user).
But if you want a slightly different pizza after (navigate to another page) you have to call again the pizzeria and have another full pizza delivered
Let’s have a look at a response of a simple server-side rendered app.
Press enter or click to view image in full size
This is the response of a simple to-do app built with Nuxt using SSR.
If this is not self-speaking to you, don’t worry, A lot of developers (I’m one of this :D) don’t really know, or don’t fully understand, the output of the modern frameworks, and one of the reasons is that these frameworks do a lot of stuff.
Anyway, the thing that we really need to look at in this example is that the body of the HTML contains some data, in this case, it’s just a list of to-do (that comes from an API call made by the server), represented by label and checkbox, but inside here there could be anything.
Also in the head, there are some meta elements, and those can be used to enrich SEO and other useful things. All of this could contain user-specific data because every response built with SSR can be different per user, this is the most important thing.
Pros
Why should you consider SSR? Is it still useful after all these years? Yes it is!
- SEO friendly: after Client-Side Rendered apps started to rise years ago, this was the main point that was leading software engineers to choose SSR over CSR (and it still is). Being the response fully populated with the data, every SEO crawler (even if it doesn’t have a Javascript engine) is able to read the response, analyze it and understand what’s there, leading to better indexing, the possibility to index every URL of your application, etc.
- Fast load time: as said before, when the response reaches the browser, the rendering phase is pretty straightforward because the HTML structure and the data are already there, so the browser has to work less (compared to CSR at least, more on this later).
Cons
What are the downsides? Why was client-side rendering “invented”?
- Cost: you must have a server up and running 24/7 to handle client requests. You can find some cheap server hosting but it’s still a cost that is going to be there (also for high traffic applications a cheap server won’t be enough).
- Slower page transition: I like to explain this as “old navigation experience”. When the application is being served this way, when you click a link to navigate on another page (of the same website) the page is going to fully reload, you can’t have a “smooth transition”.
- Caching: configuring cache is usually harder on SSR apps, especially for inexperienced developers (but also for experienced ones, believe me).
- It may have a high time to interact: this is true if you serve an application by using a framework like Vue or React and thus there will be a hydration phase where the user sees a pretty page but cannot interact with it (we will talk more about this in the pre-rendering chapter below, but if you are interested in the hydration, read this chapter)
There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton
Tools
Being the oldest method, there are thousands of choices out there, from the beloved WordPress to the widely used Express for node lovers (but it’s not actively maintained so I’ll consider koa or fastify instead). But really there are so many choices out there, for every language you can think of (probably not for funny languages like ArnoldC, I’m sorry Schwarz fans) there are going to be some framework/library to create a web server in just a couple of steps.
What it’s is great for
The first thing I look at in the requirements is SEO, if SEO is not a requirement I probably don’t opt for this approach mainly because of the cost/maintenance, but if you come from a backend background actually SSR can feel easier for you.
It fits perfectly for applications that need SEO and has highly dynamic content (e.g., not a personal blog, for that I would opt for pre-rendering, explained later).
Client-Side Rendering (CSR)
This is usually called also Single Page Applications and it looks like it’s been around since the early 2000s (feeling old yet?).
This is pretty much the opposite approach compared to SSR: the client makes a request for a website to the server, the server takes a static file (usually an almost empty HTML file), and immediately sends it back to the client.
Note that in this case, the server is not building an HTML, is not populating anything, it just sends the file, this is a key piece because having just to return a static file means that we can store and serve these files through a CDN, no server to keep up and running.
When the browser receives this response it reads it and usually, he must “build the page”.
What do I mean by building the page? The browser needs to parse the file, this usually contains just some links to other static assets like js and css files, he fetches them, interprets, and executes the javascript. This is it. All the logic to build the page is in the js files. They contain the logic to fetch the necessary data from external APIs, the logic to handle results, the code to build the HTML dynamically based on those responses, etc.
So the Italian ELI5 would be: you are the same guy as before and you order a pepperoni pizza. The delivery guy comes to you with an empty plate and the recipe for the pizza that contains also the list of places to go for the ingredients (all the links and other files you may need). You then have to go retrieve these and make yourself the pizza (build the HTML and render everything).
The good part is that if you need to add an ingredient later (navigate to another page) you just need to go retrieve that ingredient and put it on the pizza, you don’t need to re-order everything
Press enter or click to view image in full size
This is a sample response of a CSR app.
Note how in this case the body of the page is almost empty, it just contains some scripts to load. These scripts will be responsible for “building the page” as I said before. In client-side rendered apps this file is going to be served to every client request, no matter who’s requesting it. So in this case the to-do elements are not rendered yet because the API call and the creation of the relative HTML will be done later, in the browser.
Pros
Let’s see why client-Side Rendered applications became super popular in the previous decade:
- Smoother (seems native) page transitions: when a single page application is rendered, all the subsequent navigations are handled by the client, no more reloading pages on click. It feels a lot more “native” and snappy to navigate through an application made this way.
- Caching: as we said the server just has to return the same HTML (and then also the other static files, js, CSS, etc…). This means that we can cache files more easily and more aggressively, there is less logic implied for the cache strategies.
- Cost: even if this is implied in previous points I like to explicitly point this out. To host a Single Page Applications you just need static hosting, and as of today you can find this service free almost everywhere, so this is a very cheap solution (great for hobby projects).
Cons
Obviously, not all that glitters is gold
- Not SEO friendly: being the opposite of SSR this is probably the major weakness. The file returned from the server is pretty much empty (and it’s always the same, it cannot contain dynamic data), so crawlers need a JavaScript engine to get some information, but even with that SEO won’t work great, or at least is not easily predictable
- Slower initial load: the first load of the application is slower than all the other approaches (because the browser needs to do all the heavy lifting).
What it is great for
I usually choose CSR for all the applications that don’t need SEO and where I don’t want to add a layer of complexity (for frontend developers these apps usually are easier to reason on), for example, B2B applications where all the app is protected by login in my opinion perfectly fits here.
Tools
I think this is the point where there was a major “explosion” of tools and frameworks. The frontend ecosystem evolved so much in the last 10 years… So there are again thousand of choices out there. The most famous, modern, and established in my opinion are (I won’t describe these but I’ll link their website):
There are plenty of articles that feed the “frontend framework war”, I personally think that all these frameworks are amazing, this is why they are so established).
Get Alberto De Agostini’s stories in your inbox
Join Medium for free to get updates from this writer.
I must point out that these frameworks also give you the ability to build SSR apps, but this is out of the scope of this article, they don’t do it simply out of the box.
Pre-rendering
I feel that this became fashionable later than its brothers.
I think it was popularised by Jekyll in 2008 (but I’m not really sure) and became really popular in the last 5–7 years.
It is a bit of a merge between SSR and CSR and it is especially great for some use-cases (but not for others, like every technique).
Pre-rendering is actually a server-side Rendering technique (pages are not rendered on the client machine, so it’s server-side), the main difference is that the rendering part is done at build time, not when the user requests the page. When the developer makes the website, as the last step he builds it (with apposite tools), in this phase, the produced static files are filled with all the data, etc, exactly what happened in the SSR when the client asked for a webpage, but this time is done at build time, not when the client asks for it. This has huge implications:
- the output is a set of static files, so we can host the built applications using just static hosting (so easily cacheable, cheap, etc…), just like the client-side rendered apps
- each route has to be known at build time to be generated. This is the biggest downside of this approach, if you have an e-commerce app in which every item has its own detail page with the id in the URL, pre-rendering is not going to be easy because you should rebuild and deploy the application every time an item is added (it’s possible and there are new techniques that help you with this, but it’s not easy), otherwise its detail page won’t exist.
- the generated files cannot have user-specific data inserted on build time (otherwise every user would receive the same data, and if it’s user-specific is not to be great), so to enable this feature the part that needs this information is going to be rendered client-side, this is why static generated is somehow a mix between CRS and SSR apps in my opinion. The client receives a page that is already filled with all the information that is not related to the user, and he handles the rest.
So how would this be in the Italian stereotype?
The pizzeria only offers you pizza margherita, but they also give you the recipe and information to ‘enhance’ your pizza. So you receive a perfect (and already cooked) margherita and then you just need to fetch other ingredients and put them on the pizza. If you don’t have to personalize the pizza, you are perfect with the margherita that they deliver to you.
This is an example of the response:
Press enter or click to view image in full size
This is pretty much the same result that you get with the SSR. The difference is that this file is generated at build time, with SSR is generated when the user requests the page.
Pros
This approach has most of the benefits of CSR because to host the application is the same to host a CSR one, so:
- easily cacheable
- cheap (no server up and running needed)
- this approach actually is also SEO friendly because you have a pre-filled HTML file for each generated route, so SEO data is going to be there as soon as the crawlers analyse the site.
- another pro point is the fast initial rendering (usually with this technique you achieve the faster initial rendering of all the techniques) because as in SSR, the page is already filled with data, but it’s server by CDNs with nice caching capabilities.
Cons
By reading the pros it seems the best approach, but let’s see what the downsides are:
- can be difficult if there is a lot of dynamic data or user-specific data: the website is built at build time, and for each route there will be a related HTML file. Those files are filled with the necessary data, but they can only contain data that is not user-specific or dynamic, there can be no username of the logged user, otherwise, every user would receive the HTML with the same username. Or, for example, if you want to show a suggested blog post to the current user, based on his reads, you cannot do it at build time again. So all this kind of logic has to be handled client-side (by fetching necessary data via API and then building the needed parts on the page. If you have a lot of logic like this, pre-rendering can actually make your life harder).
- More deploys: an example is worth a thousand words. Imagine you have your blog built this way (it’s not a random example, blogs are the perfect example of pre-rendered apps, they fit perfectly), when you add a new blog post you will have to build and deploy the entire application to have the new static file associated to the new blog post.
So if you have a highly dynamic site this can be an issue (that these days is being addressed seriously by some frameworks). - the website is not going to be immediately interactive: when the response reaches the browser it will be immediately rendered and pretty. But the js code is going to be parsed when the render phase is done, this means that all the click listener and other logic that the user expects to be there when the page is pretty can actually not be there yet. So if the user tries to interact with a button immediately, there is the possibility that the website won’t do anything (this phase is called hydration, you can read more about it in rendering for the web and in the cost of hydration). This seems not a big issue but if you have a big application it can be a bit weird and in some cases, you will need to do something to prevent the user from becoming frustrated (like showing a loader or something).
What is great for
Pre-rendering is a great technique that became a lot popular in recent years, obviously, there is no silver bullet. I choose pre-rendering for applications that benefit from SEO and that are not heavily reliant on user-specific data. Examples are tech blogs (where maybe you can register, but the majority of the content/layout does not depend on the logged user).
It can be useful if you don’t want to use SSR due to costs but you still want to improve the loading time of your app (read more about first contentful paint)
Tools
In recent years (thanks also to Netlify) a lot of static-site-generators were born, you can find some for every language (and tons for javascript). I think a great list can be found here but if you have a preference for a framework you can just google something like “vue static site generator” and you will not be disappointed most of the time.
JAMstack
So what is JAMstack, is it a “competitor” CSR, SSR, etc?
Nope. I immediately leave “the source” to learn more about it.
JAMstack is a “word” coined by the current Netlify CEO (Mathias Biilmann) if I’m not mistaken.
Again, another Netlify website that explains this very well.
Literally, JAMstack means “Javascript Api Markdown Stack”, so this can be applied to a lot of (already existing) projects, you may be working on a JAMstack project without even knowing it.
But what it really means (at least in my opinion, but kinda confirmed by Netlify devs and CEO in this amazing podcast, I suggest all the episodes really) is an approach to web development, where a lot of functionalities (like authentication) are outsourced to third-party APIs (decoupled from the frontend application), and the HTML and CSS is pre-rendered (as more as possible).
So actually JAMstack uses pre-rendering and enforces other principles. I won’t dive deep into this, but if you are interested I think a very nice read about this in this article byJessica Chin.
front-end developers gain the ability to focus their areas of expertise, rather than trying to be jacks of all trades, and masters of none.
- Mathias Biilmann & Phil Hawksworth
Universal applications
Did you notice how CRS and SSR are pretty much the opposite (not only do they work completely different, but their pros and cons are pretty much opposite)?
“Universal application enters the game”
You can find them called also Isomorphic applications.
Basically, it is the merging of the two worlds, trying to use each on its strong point, so when a client requests a universal app the server responds with a full-page (built on the server, so server-side rendered) and this gets the SEO advantage, the speed, etc. Then when the client clicks on a link to go on another page (of the same app) for example, this navigation is handled client-side, so the transition is smooth, no refresh is done.
This basically merges the best of both worlds, and it’s very used lately thanks to frameworks like Next, Nuxt, and others that help you build in this way without needing to smash your head on the keyboard to make things work.
In Italian: you can order the pizza you want and the delivery boy will bring a perfect and ready pizza plus the recipe and info you need to change it.
You really can’t desire more
Pros
- SEO friendly
- Fast load time
- Smooth page transition
Cons
- Cost: same as SSR, you need a server up and running to do this
- Complexity: this approach is a bit more complex than others because every page can be rendered both client-side and server-side. This means that sometimes you have to check in which environment you are before executing some code (e.g. you cannot use browser APIs safely because that code could be running on the server).
What it is good for
Well, in my opinion, these applications are nice for almost anything, they really are better than both SSR and CSR applications. But, there is always a but… I think that the increase of complexity is not worth if your application can be a simple client-side rendered app (if you don’t need SEO for example), I believe that any increase in complexity must be weighed against its gain, so always put the pros and the cons in the balance of your context. Another example is blogs or other apps that better fit the static rendering approach in my opinion.
Tools
It’s probably just my lack of knowledge, but it seems to me that the landscape here is not as full as in other cases, I know that Next.js and Nuxt.js are great for this, I never tried Svelte Kit but I’m sure it’s great too.
There is another promising framework here called Astro that is framework agnostic and promises less javascript shipped to the client, but I never tried this neither.
I’m sure there are more tools for universal applications but none come to my mind now, feel free to add them in the comment section
Conclusions
I hope this can be of help to somebody. As I said in the beginning, these are just my opinions, and you are free to disagree on every single point (in case let’s talk about it in the comment section or reach me on Twitter).
Disclaimer
No Italian has been mistreated or forced to eat pizzas with pineapple during the writing of this article.
And if you are wondering if you should put pineapples on pizza…
More content at plainenglish.io. Sign up for our free weekly newsletter here.