HTML video tutorial: Client-side or server-side rendering?

In this video, I invite you to discover the different rendering methods possible for a web site/application.

Terminology

Before starting a small point on the terminology related to all the problems of Web rendering.

  • SSR Server-Side RenderingHTML rendering is done on the server side.
  • CSR (Client-Side Rendering)the rendering of the structure is done on the browser side by manipulating the DOM.
  • Hydrationwiring JavaScript views to the framework already rendered on the server side.
  • Prerenderingwe run the client-side code to render the page and save the rendered HTML static.
  • Dynamic Renderingconsists of delivering a static HTML version of the site to search engines.

And here are some key times to talk about the loading of a web page

  • TTFB: Time to First Byte represents the time between the click on a link and the first bit received.
  • FP: FirstPaintrepresents the moment when the first pixel becomes visible on the user’s screen.
  • FCP: First Contentful Paintindicates when the requested content (article, product) becomes visible on the screen.
  • TTI: Time To Interactiveindicates when the page becomes fully interactive (event listeners connected…).

HTML objective

For a web page to be visible to our users, HTML code is required, but this code can be generated in 2 ways:

  • On the server side, the complete HTML code is returned directly during the HTTP request.
  • On the client side, the HTML code is generated on the browser side by the JavaScript that will manipulate the DOM

Server-side rendering

As the name suggests, in this type of rendering, it is the server that is responsible for sending the HTML code of the page back to the browser. The page may be rendered dynamically via a server-side programming language (PHP, JavaScript, Ruby, Python…) or via simple HTML files.

Advantages :

  • Fast initial loading
  • Best SEO
  • Technological choices, we control the execution context and we can therefore choose the language to use

Disadvantages:

  • Slower consecutive navigation (each navigation reloads the whole page)
  • No element is persisted between pages (video/audio player, chat or other)
  • Higher server load (because the server has to reload all page content for each request).

Client side rendering

In this type of rendering, the code will be generated on the client side via JavaScript code executed on the browser side. The server will simply return a simple HTML structure which will be modified later.

Advantages :

  • Smoother navigation between pages
  • No total reloading of the page at the slightest interaction
  • Main page in static HTML, so easy to deploy

Disadvantages:

  • Longer initial load, because you have to execute the JavaScript and then wait for the data.
  • Imposed technology (JavaScript) and we do not control the execution context.
  • Difficult to index, some search engines can index JavaScript, but not in the first phase.
  • Separate architecture (API on one side and client code on the other) adds complexity.

Only 2 approaches?

In reality, these 2 approaches simply do not exist and it is possible to mix things up by adding the 2 types of rendering in order to maximize the user experience. However, these “hybrid” approaches will have a server-side or client-side basis.

SSR with progressive improvement

The objective of this approach is to continue doing our rendering on the server side and to add a slight overlay of JavaScript that will make the page more dynamic. For example, when you click on a link, rather than letting the browser load the new page, the new content will be loaded in JavaScript then part of the content will be injected into the current page. This makes it possible to have a smoother browsing experience, but also to keep certain persistent elements during browsing in order to counterbalance one of the drawbacks that we had seen previously. This approach can be adopted through technologies like Hotwire or Unpoly.
For micro-interactions, it is possible to use tools like AlpineJS which will allow, by inserting HTML attributes, to energize the page.

<div x-data="{ open: false }">
    <button @click="open = true">Afficher le spoiler</button>

    <span x-show="open">
      Le héro il meurt à la fin mais en fait il n'est pas vraiment mort !
    </span>
</div>

The particularity of this approach is that the server remains the main responsible for HTML rendering and user interactions. The JavaScript code that will be written will often be related to DOM manipulation

SSR with partial hydration

In this approach, we will render almost all of the HTML structure on the server side, but with some elements that will be rendered on the client side via JavaScript. For example, we can rely on the Custom Elements API to create elements that will be loaded mainly on the client side:

<article>
    <h1>Titre de l'article</h1>
    <p>Contenu de l'article...</p>
    <hr/>
    <post-comments post-id="3"></post-comments>
</article>

In this approach, the JavaScript will take care of the HTML rendering of these elements and we will therefore have a mix between elements rendered on the server side and elements rendered on the client side, which can be complex to maintain. This approach can also be combined with the previous approach if necessary.

CSR with server-side rendering

The main problem with client-side rendering is its lack of SEO and slower initial rendering. To counterbalance this problem, one can choose to do server-side rendering for the initial load by using a JavaScript rendering engine (via NodeJS) to render an HTML version of the page requested by the user. It is this static version that we will deliver during the first request made to our server. The JavaScript will then take over by hydrating the page (it will also render the structure of the page and connect the various events to the DOM rendered by the server). The rest of the navigation will then be done on the client side.

This allows for a site that is searchable since the HTML structure can be generated on the server side and allows for faster initial loading for the user. On the other hand, this is more complex to set up and we are generally more limited in terms of technology:

CSR with Dynamic Rendering

The objective of thedynamic dispaly and to ensure that our site created on the client side can be referenced. For this, the type of rendering will be adapted according to who visits the site. If the site is crawled by a search engine indexing robot, it will be delivered an HTML version of the site, while a traditional visitor will continue to receive the client-side version.

To do the HTML rendering, we will use a headless browser (usable on the command line without visual feedback) which will load the entire site (while waiting for the execution of the JavaScript and the DOM modifications) and save the final HTML rendering. This HTML structure will then be delivered to the indexing engine when they try to access a page (the rendering will also be cached to respond faster next time).

It is an approach that is quite complex to set up, but which can be interesting as a last resort to make a site created on the client side indexable.