Content
What is it?
Server-Side Rendering (SSR) is a technique for rendering a website in the server 1 before sending it to the client's browser; and therefore the client can get a static site, already rendered with their own preferences and data. This is in contraposition to Client-Side Rendering (CSR), where (almost) no HTML is shipped, and instead the client receives all the JS code to locally render the website.
If SSR sounds familiar, it's because that's how sites used to work in the PHP era. What makes it interesting this time around is something called hydration. This technique allows you to add interactivity to the SSR'd site after it loads, getting the snappiness of a CSR app (and even Client-Side routing), with all the advantages of an SSR app, which will be discussed later. Hydration can be total (all the components in a view are either hydrated or not) or partial (you can hydrate only the components you need to be interactive) at any time; though partial hydration is not implemented by every framework.
This method has been gaining a lot of popularity with the advent of frameworks like SvelteKit, Next.js, Nuxt.js, and Astro, which allow you to write code in the familiar syntax of your favourite front-end framework, but compile it to run as SSR, optionally using hydration, in a rather seamless way.
The good
Performance
The fact that only a static HTML needs to be shipped for the site to be rendered, instead of needing to make multiple requests to load all the necessary JS files (which often include the framework's own code, making it several MB in size), is a game-changer in terms of initial load times and "time-to-content". Additionally, often times no data fetching will be necessary after the initial load, since everything needed to render the page will have been fetched server-side. Also, since these frameworks do code-splitting automatically, only the current view's code needs to be loaded for the initial render, whereas in a CSR Single Page Applications (SPA), even the code for views you'll never see get loaded before you can see any content.
You may be thinking that page transitions will feel slower than in SPAs, since before each navigation you'll need to load the new code, but SSR frameworks include ways of preloading in the background content you may need soon, so transition feel as snappy as they do in SPAs.
As an example, this site's home page can be fully functional after loading only 9.6kB 2 . Here's the Lighthouse results for that page:
Go ahead. Reload this website. Open it in incognito. Share it with some friends while you're at it. It'll load blazingly fast every single time.
Accessibility and privacy
I love the idea that no JS is needed to render the site, since it has amazing implications for both accessibility and privacy. You can literally disable JS in this site using NoScript, and everything will work just fine, with the only exception being the theme switcher 3
Firstly, when it comes to privacy, obviously companies can keep tracking you even if you disable JS using cookies, your IP, and many other ways. However, many of these tracking means can be somewhat mitigated using a browser that blocks cookies, the Tor network 4, etc. Many tracking methods that are harder to avoid use JS to identify your browsing habits, such as the way you type, how you move your mouse, how long you look at a certain piece of content (or ad), etc. Therefore, blocking JS execution can make your browsing more private, and that's why some of the more private browsers (like the Tor browser4) block it by default.
Sadly, basically any CSR site will unavoidably break if you disable JS. That's why I believe it's great that maybe the next generation of websites will not need any JavaScript to run.
Secondly, JavaScript may not be great for accessibility reasons:
- Older browsers may not have great JS support
- Sometimes CPU usage during rendering can be significant with CSR apps, making the browsing experience feel sluggish in older devices
- SSR also reduces mobile data usage, due to the many reasons explained in the performance section
- Having the contents of the page move as it's being rendered Client-Side can be uncomfortable for some people
- I don't know how much of an issue this is as of today, but it used to be the case that some screen reader software may have issues with Single Page Applications
SEO
Search engines need to be able to read the content, in order to be able to index it properly. While modern search engines are able to index JS that's executed synchronously, they won't make all the necessary requests to fully load a CSR application, and therefore it's likely that not all the content will be indexed, potentially damaging the site's ranking.
The bad
Hosting
If you want to take advantage of all the features SSR provides, a simple static site hosting service won't do. You'll either need to pay for a server and manage it yourself, or pay for some serverless 5 backend service.
Since these can get pretty expensive, and I'm not about to shell out real money for a glorified portfolio site, I ended up opting for using Static Site Generation (SSG) (with hydration). This means that the site is rendered at compile time instead of at request time. This way, you get many of the performance, SEO and accessibility advantages of SSR, and you can host it in your typical static site host. The main limitation this has is that you lose the ability to customize the site for each client on the server side, since everyone will receive the exact same HTML rendered at compile time.
It's important to note that many SSR frameworks seamlessly support SSG, and at least in SvelteKit activating it is as easy as changing a config file.
Added complexity and testing
With SSR/SSG, your site not only needs to run properly on the client side, but also on the server side (or at build time in the case of SSG). This means that you have to test some things twice. Even in this relatively simple site, I've had some things that do work on the browser but not on the server, or vice versa.
This may be in part due to my inexperience building SSR sites, since at least some of the errors were for example from using APIs that do not exist in one of the two environments (for example, you can only access document in the browser); however I get the feeling that even more experience devs will from time to time have to face some hard-to-reproduce issue because of this, and it makes me wonder how automated testing could be used to prevent this type of problem (though I haven't looked much into this).
On SvelteKit
SvelteKit is an amazing framework. It inherits all of the great things Svelte had (speed, simplicity, light weight, reactivity through stores, etc), and provides an easy way of adding SSR (or SSG) and hydration.
This site was initially built using Svelte (i.e. CSR), and halfway through I decided to migrate to SvelteKit, which only took a few hours. This is a testament to how simple it is to add SSR to an existing Svelte app. I found that developing in SvelteKit was quite fast, and above all it was fun.
The one big issue it has, which I'm hoping will soon stop being an issue now that the first official release is out 6 is that breaking changes were way too frequent while building this site. Fortunately, the compiler is smart enough to warn you and suggest fixes if it detects you're using a deprecated API, so it wasn't that hard to fix what broke.
Conclusion
I'm extremely optimistic about about SSR. Even though there are some obstacles that need to be addressed, I'm hopeful that this technology will allow for a more private (not to mention generally more performant) internet.
However, should you use it in its current state? I think it depends. For a personal website like this one, a fun project, something you do to learn something new? Sure, it's extremely fun, and I believe at some point it will become a really valuable skill. For some corporate project that is supposed to last for decades, be 100% stable, and minimize server costs? Maybe. But it is important to take into account that many of these frameworks are rather new (at least compared to the CSR alternatives), barely battle-tested, and see frequent breaking changes. I feel that I'd need to see it pass the test of time before being comfortable recommending it in every situation.