Web rendering approaches
Learning objectives
- You know of different approaches for rendering content shown to users.
- You know possibilities for client-side and server-side rendering, including static site generation and lazy loading.
We briefly highlighted some benefits and downsides of client-side web development, discussing server-side rendering and client-side functionality in general. To avoid a biased view that leans towards one or the other, let's take a look into some techniques for creating content shown on the web.
Serving static files
The starting point of all web applications was static web sites, which were served to clients on demand. The static web sites included static HTML, stylesheets, JavaScript files, images, etc, and were created by hand, possibly using WYSIWYG tools such as DreamWeawer. The sole role of the server was to serve the files.
The role of serving files has not changed for the server, but the tasks that servers are used for has since expanded.
Server-side rendering
As additional expectations emerged, including simple things such as not needing to copy and paste the same header and footer content to each and every HTML file, dynamic functionality was introduced to web applications. Server-side rendering is a solution where HTML is produced on the server programmatically, for example, by combining multiple files into one, possibly also retrieving data from a database and filling the data into a resulting HTML document.
For classic view on server-side rendering, check out the part on View Templates in the Web Software Development course.
While server-side rendering is classically done per request, where an HTML document is produced for each request (omitting caching), some content -- if not all -- can also be generated beforehand.
Static site generation
Static site generation allows serving a site with dynamic content as a static website, which when served requires no dynamic rendering from the client or from the server. This, of course, requires that the content is such that it does not change per request. For example, if a website uses static site generation and depends on contents from a database, the static content needs to be recreated when the contents of the database change.
As an example of an early "static site generator" from the 1990s, JavaDoc -- a documentation generator for Java code -- allowed generating HTML-based API documentation from comments written in Java source code files.
Client-side rendering
Client-side rendering allows the creation of web sites where browsers load an HTML document with JavaScript, followed by the JavaScript being executed, leading to retrieving additional content. The JavaScript code may, for example, retrieve template HTML code and JSON, merging them programmatically on the client to create the shown content. This allows a situation, where interactions with the server do not require a full page reload, but instead change only parts of a site -- as an example, form data can be sent using JavaScript, which would also be used to process and display the response from the server.
While client-side rendering has many benefits including increased usability, one of the downsides is that it is classically not search engine friendly. As crawlers visit web sites, they read and process the contents but do not necessarily execute any JavaScript on the site. This leads to a situation, where the content of a website might not be properly entered into search engines.
On the other hand, client-side rendering allows more fine-grained control to what is being shown. As an example, with JavaScript, developers have access to information on whether a component is visible on a site, which allows controlling whether and when that component should be loaded. As an example, it may be sensible to load media only when it is within the viewport of the browser (or about to enter the viewportt), instead of loading it during initial page load. This approach is called lazy loading, and it can improve the initial load time of a web page, and consequently also reduce the load imposed on a server.
Here, user interface frameworks such as React and Svelte become handy. While React is discussed in Full Stack Open, we'll briefly look into Svelte in a moment in Chapter 8.
Hybrid and isomorphic rendering
Server-side and client-side rendering are often used in tandem to reach a desired outcome -- this is called hybrid rendering. The server could, for example, be responsible for creating a outline of the website, which is then sent to the client. The client, in turn, could fill in parts of the website based on additional information, and react to interactions without the need to reload the full page contents.
As an example of hybrid rendering, take a peek at Astro, which we'll also delve into in more detail in a moment in Chapter 9.
Isomorphic rendering is an instance of hybrid rendering, where both the client and the server use the same functionality for rendering the content. In practice, with isomorphic rendering, one could for example receive a rendered website from the server, which would also contain JavaScript for added interactivity. When the client scrolls the website or interacts with it in a way that requires additional data, the client would retrieve the data from the server (e.g. in JSON format), and render it as an addition to the existing content created on the server.
Compilation, minification and compression
Note that when writing web applications, the development process often involves tooling that processes the written code. As an example, compilation and transpilation of (client-side) source code allows developers to use modern language features and syntax, while maintaining compatibility with older browsers.
This tooling also often includes support for mechanisms such as code-splitting, which allows dividing code into smaller parts, which can be loaded when needed. Although this does not reduce the overall amount of cide, this can reduce the amount of code that is initially sent to the client, improving the perceived performance of the application.
In addition, when deploying a website, the source code can also be minified and compressed. Minification refers to removing unnecessary characters from the source code, such as white spaces, linebreaks, and comments, shortening variable and function names, and potentially doing other trickery for making the code smaller and faster to download. The result of minification can also be compressed, leading to even smaller content that is again faster to download; the majority of browsers support handling compressed content.