SSR vs CSR
Client-side rendering
CSR - With a client-side rendering solution, when the user opens your website, his browser makes a request to the server, and the user gets a response with a single HTML file without any content, loading screen, e.t.c. It’s a blank page until the browser fetches all linked JavaScripts and lets the browser compile everything before rendering the content.
All logic, rendering and booting are done on the client. The result is usually a huge gap between Time To Interactive and First Contentful Paint. As a result, applications often feel sluggish as the entire app has to be booted on the client to render anything.
As JavaScript has a performance cost, as the amount of JavaScript grows with an application, aggressive code-splitting and deferring JavaScript will be absolutely necessary to tame the impact of JavaScript. For such cases, a server-side rendering will usually be a better approach in case not much interactivity is required.
Server-side rendering
SSR is not a new concept. It has been used since the first backend solution, like PHP or JAVA. Server-side rendering is a method to render your website. When the user opens your page, his browser makes a request to the server, and the server generates ready to provide HTML.
In classic SSR, such as WordPress, all requests are handled entirely on the server. The requested content is returned as a finished HTML page and browsers can render it right away. Hence, SSR-apps can’t really make use of the DOM APIs, for example. The gap between First Contentful Paint and Time to Interactive is usually small, and the page can be rendered right away as HTML is being streamed to the browser.
This avoids additional round-trips for data fetching and templating on the client, since it’s handled before the browser gets a response. However, we end up with longer server think time and consequently Time To First Byte and we don’t make use of responsive and rich features of modern applications.
CSR vs SSR
CRITERIA
CSR
SSR
Ideal For
If you building a SPA (single page application), and you don’t want to configure everything on the server-side like: i18n, router e.t.c. you can just use create-react-app, angular-cli, vue-cli, etc
If you want to build a site that is mostly static (blog, portfolio, a landing page), use frameworks like Gatsby, it’s not SSR, but it pre-renders the website into HTML at the build time
If you want to build a web app and you care about SEO, easier social media optimization and faster render for user you should think about SSR and framework like next.js, nuxt.js, etc
General Summary
Pros:
Fast render after initial load
Faster navigation
Lower server load
Remarkable for web apps
Cons:
Slower initial load
Unpredictable performance – you never know if your user will open and ‘compile’ your website on a mobile device with a very slow internet connection or not updated browser
Client-side routing solutions can delay web crawling.
SEO – if you not implemented correctly
Initial req loads the page, CSS, layout, js,
Some or all content is not included
Pros:
SEO friendly – SSR guarantees your pages are easily indexable by search engines
Better performance for the user – User will see the content faster
Social Media Optimization: When people try to post your link on Facebook, Twitter, etc. then a nice preview will show up with the page title, description, and image.
Shared code with backend node
User-machine is less busy
Cons:
TTFB (Time to first byte) is slower; your server has to spend some time preparing HTML for your page instead of sending almost empty HTML doc with link to javascript
The server will be busier, can execute fewer request per second
HTML doc will be bigger
The page is viewable sooner, but it’s not interactive and the beginning, a user has to wait until react will be done executing
Full page reload after routes change
Speed
In client-side-rendering, non-content can be displayed until browser will download all the js files.
A blank page is much longer on client-side-rendering, as a developer you have to avoid it using some loader, or loading screen
In server-side-rendering user will get HTML rendered much faster than in client-side-rendering (First Contentful Paint). But while the page is rendered earlier and the customer can see the page sooner, they can’t really interact with it until react is done executing. If the customer is really fast and clicks a button, the action won’t be executed until React is done executing;
SSR TTFB(Time To First Byte)is slower than CSR, because your server will have to spend the time to create the HTML for your page instead of just sending out a relatively empty response;
SSR throughput of your server is significantly less than CSR throughput. For react in particular, the throughput impact is extremely large.
Image is faster available with SSR compared to CSR, because when using CSR the images cannot be downloaded before linked js files, HTML is not ready
SEO (Search Engine Optimization)
CSR is not very SEO-friendly. It’s primarily because the majority of single-page applications are run on JavaScript, which most search engines do not support. Web pages are indexed through “crawling” or “spidering”. Search engine crawlers download the page’s HTML files which makes static HTML web-pages are easier to rank.
In the last couple of years, Google has become much better at indexing JavaScript. Still, Google admits it sometimes can’t properly index single-page applications. Not to mention that other search engines haven’t yet achieved the same SPA-crawling prowess.
Article for SPA SEO optimization: https://snipcart.com/spa-seo
SSR enables better website positioning as each page can be optimized for a different keyword. Also, meta tags can be included on every page – this positively impacts Google rankings.
Mobile Adaptivity
Unpredictable performance or behavior – you never know if your user will open and ‘compile’ your website on a mobile device with a very slow internet connection or not updated browser
Server-side device detection works by using the User-Agent string to uniquely identify the client device type. By matching this against a database of device capabilities, relevant details about the user’s device can be known, and can be used to tailor an optimized response for that device.
Deployment
A single page application is super-simple to deploy: it's really just one index.html file, with a CSS bundle and a Javascript bundle.
These 3 static files can be uploaded to any static content server like Apache, Nginx, Amazon S3 or Firebase Hosting.
Other types of rendering

Static Rendering We build out the product as a single page application, but all pages are prerendered to static HTML with minimal JavaScript as a build step. That means that with static rendering, we produce individual HTML files for every possible URL ahead of time, which is something not many applications can afford. But because the HTML for a page doesn't have to be generated on the fly, we can achieve a consistently fast Time To First Byte. Thus, we can display a landing page quickly and then prefetch a SPA-framework for subsequent pages.
Server-Side Rendering With (Re)Hydration (Universal Rendering, SSR + CSR) We can try to use the best of both worlds — the SSR and the CSR approaches. With hydration in the mix, the HTML page returned from the server also contains a script that loads a fully-fledged client-side application. Ideally, that achieve a fast First Contentful Paint (like SSR) and then continue rendering with (re)hydration. Unfortunately, that's rarely the case. More often, the page does look ready but it can't respond to user's input, producing rage clicks and abandonments. The approach has its downsides. As a result, we do gain full flexibility of client-side apps while providing faster server-side rendering, but we also end up with a longer gap between First Contentful Paint and Time To Interactive and increased First Input Delay.
Streaming Server-Side Rendering With Progressive Hydration (SSR + CSR) To minimize the gap between Time To Interactive and First Contentful Paint, we render multiple requests at once and send down content in chunks as they get generated. So we don’t have to wait for the full string of HTML before sending content to the browser, and hence improve Time To First Byte.
On the client-side, rather than booting the entire application at once, we boot up components progressively. Sections of the applications are first broken down into standalone scripts with code splitting and then hydrated gradually (in order of our priorities). In fact, we can hydrate critical components first, while the rest could be hydrated later. The role of client-side and server-side rendering can then be defined differently per component. We can then also defer hydration of some components until they come into view, or are needed for user interaction, or when the browser is idle.
Trisomorphic Rendering With service workers in place, we can use streaming server rendering for initial/non-JS navigations, and then have the service worker taking on rendering of HTML for navigations after it has been installed. In that case, the service worker prerenders content and enables SPA-style navigations for rendering new views in the same session. Works well when you can share the same templating and routing code between the server, client page, and service worker.
CSR With Prerendering Prerendering is similar to server-side rendering but rather than rendering pages on the server dynamically, we render the application to static HTML at build time. While static pages are fully interactive without much client-side JavaScript, prerendering works differently. Basically, it captures the initial state of a client-side application as static HTML at build time, while with prerendering the application must be booted on the client for the pages to be interactive.
The result is a better Time To First Byte and First Contentful Paint, and we reduce the gap between Time To Interactive and First Contentful Paint. We can’t use the approach if the content is expected to change much. Plus, all URLs have to be known ahead of time to generate all the pages. So some components might be rendered using prerendering, but if we need something dynamic, we have to rely on the app to fetch the content.
Last updated