Server-side rendering (SSR) has become so popular these days for enhancing the performance and SEO-readability of websites. Developers boast about it sometimes and it turns out to be a trend despite knowing its resource hungriness is the biggest pitfall. It basically involves rendering web pages on the server side before serving them to the client, rather than relying solely on client-side JavaScript to render the same. However, traditional SSR also could be slow and lead to performance issues and a suboptimal user experience.
This is where progressive server-side rendering (PSSR) steps in. PSSR is a technique that balances the benefits of SSR with the efficiency of client-side rendering (CSR), providing a faster, more responsive, and user-friendly website experience. In this article, I will try to articulate how PSSR works, its benefits, and how to implement it. Let’s look beyond the trend and try something more worthwhile.
How PSSR Works
In traditional SSR, all of the HTML, CSS, and JavaScript for each page is generated on the server upfront and sent to the client as a complete HTML document. PSSR, however, takes a hybrid approach. Instead of waiting for the server to generate an entire HTML document, PSSR sends a “shell” HTML document to the client with some basic tags and links to essential CSS and JavaScript files. This shell document has placeholders for the dynamic content that will eventually be rendered based on the user’s interaction.
As the user interacts with the website, PSSR requests the dynamic content from the server. Unlike traditional SSR, PSSR does not wait for all the dynamic content to be rendered before sending the response to the client. Instead, it streams small pieces of HTML to the client in real time as they are generated on the server, replacing the placeholders in the shell document. This gives the illusion of a fast, responsive, and user-friendly website.
Why PSSR has started earning popularity slowly?
There are several reasons actually. First, it enables web developers to create fast, responsive, and engaging user experiences, without sacrificing the benefits of server-side rendering. This is particularly important for websites that rely heavily on user interaction, such as e-commerce sites and social networks.
Second, PSSR provides a better user experience for users with slow or unreliable internet connections. By generating an initial HTML response on the server, PSSR enables web pages to load quickly and smoothly, even on slow or unreliable connections. This is particularly important for users in developing countries or rural areas, where internet connectivity can be limited or unreliable.
Finally, PSSR is also beneficial for search engine optimization (SEO). By generating an initial HTML response on the server, PSSR enables search engines to crawl and index the content of the web page more easily. This can improve the visibility and ranking of the web page in search engine results pages (SERPs), which can help drive more traffic to the website. It can also be implemented without requiring significant changes to the existing infrastructure.
I can predict a bright future for this technique which will potentially be used in frontend development in the growing e-commerce sector.
What about pitfalls?
It doesn’t have any additional pitfalls than the regular SSR approach. Still, let me state them in short.
- Overall resource hungriness will get reduced compared to SSR but it is still significant
- The initial page load may be slower due to the time required to render the page on the server before it can be sent to the client. Although it depends on the volume of the critical component rendition.
- Implementing PSSR is a bit more complex than traditional SSR, especially post-rendition data binding and user interactions.
- Sites with a high degree of dynamic content may not see significant benefits from PSSR, as the content must still be generated dynamically on the server.
Implementing PSSR
To implement PSSR, you’ll need to follow a few elementary steps:
1. Identify the pages that require PSSR based on the frequency of user interaction.
2. Create a server-side template engine to generate the shell document.
3. Configure the server to stream data to the client in real time.
4. Implement a client-side framework (e.g. React, Vue.js) to manage the dynamic content rendering.
5. Cache static assets like CSS and JavaScript files to reduce latency.
First, let’s get our hands dirty with some coding:
// client-side rendering
import React, { useState, useEffect } from 'react';
import ReactDOMServer from 'react-dom/server';
import ejs from 'ejs';
const App = () => {
const [data, setData] = useState(null);
useEffect(() => {
// fetch data asynchronously
fetch('/api/data')
.then(response => response.json())
.then(data => {
setData(data);
});
}, []);
// rendering will not get blocked by data fetching delay.
// Loading text will be shown at first.
// When the data arrives, it will progressively re-render the page again
return (
<div>
{data ? (
<p>Data loaded: {data}</p>
) : (
<p>Loading data...</p>
)}
</div>
);
};
// server-side rendering function
const renderApp = (req, res) => {
const app = ReactDOMServer.renderToString(<App />);
const data = { app };
ejs.renderFile('index.ejs', data, (err, html) => {
if (err) {
res.status(500).send('Internal server error');
} else {
res.send(html);
}
});
};
export default renderApp;
In another term, it is also called the Render-As-you-Fetch technique. I’ll write another detailed article about other rendering techniques.
So, do you want to try it out in your project? Please leave a comment with your thoughts!