Over the past years, the world of web development has evolved from simple static HTML/CSS webpages to more dynamic and interactive ones. The widespread use of JavaScript in building web applications has been one of such significant developments. As a result, JavaScript has become an essential part of any modern front-end web development workflow due to its increasing popularity as the most used programming language, combined with the diverse emerging frameworks that aim to help developers create highly interactive and scalable single-page applications.
Despite this, single-page applications aren't without their challenges since they typically delegate page rendering and routing to the client-side (browser), which presents a unique set of challenges, including slow loading times for the first contentful page and poor search engine optimization. This gave rise to the need for server-side rendering (SSR), which aims to solve problems plaguing client-side rendering in single-page applications. You've probably heard of server-side rendering if you've actively been involved in front-end development in the past few years. Although SSR isn't exactly a new concept, many people still don't fully comprehend this technique or its associated benefits.
In this article, we'll take a high-level overview of server-side rendering, its advantages and disadvantages, and how it can benefit us with better user experience, increased search engine optimization, and faster page load times.
The Origin Story
Ironically, in the early days of web development, the traditional rendering method involved some form of server-side request handling. Typically, when a user visits a website through a browser, a request is sent to the server for that webpage's content, which is then fetched, bundled, and sent over to the browser as static files. Additionally, whenever a user clicks on a related link in the webpage, a new request is sent to the server for the new content of that webpage, which in turn refreshes the browser with the newly requested web page.
This all changed with the advancement in web technology and the widespread adoption of JavaScript, which led to the emergence of AJAX (Asynchronous JavaScript And XML) — A breakthrough which gave birth to single-page applications and client-side rendering. When a user visits a website in single-page applications, a request is sent to the server for that page. The server immediately responds by sending an empty shell of an HTML file (without any pre-rendered content) along with the JavaScript responsible for later populating the empty HTML file with actual content.
Whenever a user clicks on a related link on the webpage, JavaScript intercepts this request, then using AJAX, fetches just the specific components and content of the requested web page and repopulates the HTML file with the new data without actually refreshing the entire browser. As a result, page rendering and routing happen on the client side (in the browser) since all user requests are handled by the browser using JavaScript.
However, client-side rendering comes with its own new set of challenges. Recall that when a user visits the web page, the content is initially unavailable until the JavaScript has finished loading and populated the empty HTML file sent by the server. This poses a problem for search engine bots and crawlers trying to index the page for SEO, as when they first land on the webpage, the empty shell of the HTML file is what is indexed. Additionally, this results in the slow initial rendering of the first contentful page for users when they first land on the webpage, as a blank page greets them.
What is Server-side Rendering?
Server-side rendering is an alternative to client-side rendering in single-page applications. The term "server-side rendering" describes the concept of generating a complete HTML page from JavaScript on the server in response to a URL request. Unlike client-side rendering, which generates the HTML on the client's device (in the browser), in server-side rendering, whenever a user visits a page URL through the browser, it sends a request to the server for that web page. The server responds by sending back an entirely generated or contentful HTML page to the browser (client).
Hence the name "server-side rendering," as the page rendering is now done on the server, so users and bots always get a contentful page when they visit a web page. Furthermore, when a relative link is clicked on the web page, the same pattern is repeated, with a new request getting sent to the server, which sends back a fully rendered web page.
Benefits to Server-Side Rendering?
There are several potential benefits to using server-side rendering (SSR) for web applications:
- It speeds up initial page load: First, SSR can improve web applications' performance by reducing the time the client needs to spend rendering pages. This means the user will not have to wait for the JavaScript to finish loading and generating the page before seeing the content as the server sends a full page over. In addition, JavaScript contributes significantly to the weight of a page when it is downloaded via CSR onto a browser
- Improves SEO: Server-side rendering can enhance the search engine optimization (SEO) of web applications by making it easier for search engines or bots to crawl and index the content of web pages.
- Can be Accessed Without JavaScript: Since all of the web page's content is generated on the server side, there would be no problem if a user tried to access the site without JavaScript enabled.
- Ideal for static websites: Server-side rendering is excellent for static pages because it's faster to pre-render the static page on the server before sending it to the client.
Downsides to Server-Side Rendering?
However, there are a few potential downsides to server-side rendering that should be considered before implementing it in a project:
- Complex to Set Up: It can be more complicated to set up and configure than client-side rendering, as the server must be configured to render the app correctly.
- Slow Overall Rendering Experience: Server-side rendering can lead to a slower overall page rendering experience for users than client-side rendering, as the server must generate the HTML for each page on each page request.
- Requires More Server Resources: Server-side rendering can use more server resources with frequent server requests than client-side rendering. As the server has to generate HTML for every page on demand, this can be particularly resource-intensive for websites that receive a lot of traffic.
- Not Ideal for Very Dynamic Web Apps: Getting rich site interactions using SSR can be challenging. Furthermore, it results in full-page reloads when fetching new content, even if it's only a specific portion of the page that changed.
React's Approach for SSR
React provides a solution for server-side rendering called ReactDOMServer, which is an object for pre-rendering React components on the server, typically a node server, and then hydrating the client with the React component tree. This makes it possible to generate static DOM content on the server and then pass them to the client using the hydrate() function, which is the same as render() (for client-side rendering) but is used to hydrate elements rendered by ReactDOMServer on the server to the client.
Furthermore, the React 18 release attempts to improve the performance of server-side rendering with React Suspense, a React component used to suspend, pause or delay the rendering of components until all data is available to avoid loading components with pending data. However, implementing server-side rendering in vanilla React applications can be tricky, especially when dealing with frequently changing state-dependent components or dynamic web apps, as it can easily lead to a lousy user and developer experience.
Luckily, there are a few React-based SSR frameworks that make building SSR applications less complicated.
Next.js Approach for SSR
Next.js is a React-based full-stack SSR framework that comes with three different approaches to server-side rendering:
- Static Site Generation (SSG): The concept behind SSG is to generate all the static web pages ahead of request time, typically during the build time, so they're already available to be served when requested by the client. Usually, this approach is appropriate for static websites with very few dynamic elements. Otherwise, every time the website's data changes, all the web pages must be regenerated.
- Server-Side Rendering (SSR): SSR as you know it, lets you generate your web pages on the server on-demand before sending them to the client. Using this method is ideal for dynamic websites with a lot of content that changes frequently.
- Incremental Static Regeneration (ISR): This concept is very similar to SSG, the difference being to regenerate the website incrementally, at specific time intervals. This means that the website gets regenerated to reflect updated changes at intervals. In a way, this approach combines SSR with SSG, which is ideal for static websites with some dynamic content.
With Next.js, developers can switch between these approaches when building an SSR React application.
Remix’s Approach for SSR
Remix is another open-sourced, edge-first React-based framework for building full-stack SSR React applications. In contrast to Next.js, Remix approaches SSR differently by placing all stakes on only SSR instead of also having ISG and SSG solutions. Taking the SSR route is Remix's response to the problem that SSG and ISR have when dealing with websites with many pages and dynamic content, which would mean generating every page at build time, even for hypothetical scenarios such as for search results, etc.
This may seem trivial for a small-scale web application, but imagine a complex or large application with several pages, such as an e-commerce store with several products or dynamic content. Being an edge-first framework, Remix allows you to get the most out of SSR for dynamic websites by easily incorporating distributed edge systems and their infrastructure into your build instead of relying on static build for a fast SSR website.
There are other popular technologies for developing SSR applications such Nuxt, which offers Vue.js developers both static-site generation and on-demand server rendering, amongst others.
Conclusion
Server-side rendering (SSR) aims to solve real problems plaguing client-side rendering in single-page applications. However, it does come with its challenges as well as benefits. The server-side rendering process (SSR) can be tricky for those who haven't worked with it before. Still, with the help of some popular SSR technologies, depending on your needs (SSR, SSG, or ISG), you and your team can quickly get up and running in building SEO-friendly and performant websites.