The Art of Web Rendering: An Introduction
A tour through static, client-side, and server-side rendering, and why the best answer is almost always a mix.
Web rendering patterns have evolved a lot over the years, from server-side rendering to client-side rendering to hybrid approaches. But along the way, things have also become unnecessarily complex, with bloated frameworks, heavy dependencies, and fragile code. That’s why some developers are going back to the roots of web development, using simple and elegant solutions like htmx, but there’s still a lot of work that needs to be done. In this post, we’ll discuss different rendering techniques provided to us by popular frameworks such as Next.js, Svelte, Astro, etc.
But why do we need these patterns?
There are many things to keep in mind while building a great project. Build times, uptime, server costs, rollbacks, scalability, and more. Choosing the right pattern is crucial for a good user experience. When we optimize our web app we usually optimize for Core Web Vitals. Let’s discuss them briefly:
- Largest Contentful Paint (LCP): how fast your page loads the largest visible content. Aim for under 2.5 seconds.
- First Input Delay (FID): how responsive your page is to user interactions. Aim for under 100 ms.
- Cumulative Layout Shift (CLS): how stable your page layout is during loading. Aim for under 0.1.
Other vital metrics are not considered a part of user experience but are used to quantify technical factors, lag time, etc. You can read more about them on web.dev.
Static Rendering
In static rendering, you generate the HTML content for each page at build time, instead of at request time. This way, you can serve the pages faster and more reliably from a CDN or a simple server. Static rendering is perfect for pages that have static content, such as blog posts, product pages, or contact information. There are different types of static rendering, such as prerendering (creates a static HTML file for each route) or static site generation / SSG (creates a static HTML file for each possible data source). Other variants include client-side fetch using a library like SWR, incremental static regeneration (ISR), and on-demand ISR with the help of Next.js. These can be useful for static sites that still need dynamic data.
Client Side Rendering
In client-side rendering, you create dynamic and interactive web pages. Instead of generating the HTML on the server and sending it to the browser, client-side rendering uses JavaScript to build the HTML elements in the browser. This way, you can update the page without reloading it, and provide a faster and smoother user experience. Client-side rendering is great for web applications that need to handle a lot of user interactions and data changes.
Server Side Rendering
Server-side rendering (SSR) is a technique that allows you to render web pages on the server instead of the browser. This can improve the performance, SEO, and user experience of web applications. SSR works by sending a fully rendered HTML page to the browser, which can then be enhanced by client-side JavaScript. SSR can also reduce the amount of data transferred to the browser, the time and resources needed to parse and execute JavaScript code, as well as enable features like streaming.
One of the latest innovations in SSR is React Server Components, which are a new type of component that can run only on the server. They can access data sources directly, without using APIs or GraphQL, and they can render UI components that are sent to the client as HTML. This reduces the amount of JavaScript and data that the client has to download, making the app faster and more interactive.
Each pattern has its trade-offs. There is not one pattern that’s better than the others. The best solution might be a mixture of some of these techniques. Using the right rendering technique can help you create a great user experience.