server side rendering vs client side rendering
Last updated 15th.Nov.2024
Want to know more about server side rendering vs client side rendering. Then you are at the right place, this article will guide you through it.
About The Author
Sai Ram Soma Having 12+ years of IT experience in React JS & Native, JavaScript, Typescript. Working in a startup from day one. Accustomed to learning and keeping up with the current trend. Experience in developing feature rich web applications using React JS. Experience in developing mobile applications in Android, React Native.
Contents
Introduction to Server-Side Rendering (SSR) in React ?
Server-Side Rendering (SSR) is a technique that generates the HTML content of a webpage on the server side instead of the client side (browser). In the context of React, SSR involves rendering React components on the server and sending fully formed HTML to the client. This approach provides several benefits, particularly around performance optimization and Search Engine Optimization (SEO), making it a popular choice for content-heavy websites and applications.
Understanding Server-Side Rendering (SSR)
In a traditional client-side rendering (CSR) React application, the browser downloads a minimal HTML file, loads JavaScript bundles, and then executes the JavaScript to render the HTML elements on the page. This process is heavily reliant on JavaScript execution on the client side, which can lead to longer initial load times and poor performance on slower networks or less powerful devices.
SSR, on the other hand, shifts this burden from the client to the server. Here’s how it works:
- Initial Request: When a user requests a webpage, a request is sent to the server.
- Server Processes the Request: The server runs the React components associated with the requested route. Using libraries like react-dom/server, the server converts these components into static HTML strings.
- HTML Sent to the Client: The server sends the fully rendered HTML page back to the client. This HTML includes the content of the page along with any relevant meta tags, styles, and scripts.
- Hydration on the Client Side: Once the client receives the HTML, React takes over by “hydrating” the HTML. Hydration is the process where React attaches event handlers to the HTML content so that the page becomes interactive.
Benefits of Server-Side Rendering (SSR) in React
- Improved SEO: One of the most significant benefits of SSR is enhanced SEO. Search engine crawlers often struggle with JavaScript-heavy single-page applications (SPAs) that use client-side rendering because the content isn’t immediately available in the HTML. With SSR, the HTML is fully rendered on the server, allowing crawlers to index the content more effectively.
- Faster Initial Load Time: Because the server sends a fully rendered page, the user sees content much quicker than with CSR, where the browser must download and execute JavaScript before displaying content. This faster initial render improves perceived performance, particularly for users on slower connections.
- Better User Experience: Users experience faster load times and see content sooner, resulting in a smoother and more pleasant user experience. This is particularly important for public-facing websites where initial load time significantly impacts user retention and engagement.
- Efficient Use of Server Resources: SSR offloads some processing from the client to the server, which can be beneficial in environments where client devices are less powerful. Instead of the browser doing all the heavy lifting, the server does most of the work, sending a ready-to-use HTML page to the browser.
- Easy Integration with Existing Infrastructure: SSR can be easily integrated into existing server infrastructure using popular frameworks like Next.js, which provides a seamless developer experience and optimizes SSR implementation for React applications.
Challenges with Server-Side Rendering
While SSR provides several advantages, it also comes with its own set of challenges:
- Increased Server Load: The server must render pages for every request, which can lead to higher server costs and potential performance bottlenecks if not managed properly.
- Complex Implementation: SSR requires additional setup and configuration compared to CSR, including managing server routes, data fetching, and handling authentication.
- Potential Latency Issues: Since every page request involves a round trip to the server, there could be potential latency issues depending on server performance and geographical location of users.
How Server-Side Rendering (SSR) Works
Server-Side Rendering (SSR) involves generating the HTML for a web page on the server rather than in the browser. When a user requests a web page, the server prepares the HTML by running the JavaScript and React components, then sends the fully formed HTML to the browser. Let’s explore in detail how this process works step-by-step:
Step-by-Step Explanation of SSR in React
- Initial Page Request from the Client:
- When a user types a URL in the browser or clicks a link to navigate to a page, an HTTP request is sent from the client (the browser) to the server. This request asks the server for a specific resource, such as an HTML page.
- Server Receives the Request:
- The server, which hosts the application, receives the HTTP request. At this point, the server determines which React components are needed to render the requested page. For example, if the user requests the /about page, the server understands it needs to load the components associated with the “About” page.
- Server Renders React Components to HTML:
- The server uses a library like react-dom/server to render the React components to HTML strings. In this step, the server-side code executes the JavaScript logic, retrieves necessary data (if any), and combines it with the React components to generate the complete HTML content for the page. This is the core of SSR, where React’s components run on the server rather than in the browser.
- Data Fetching on the Server:
- While rendering components, the server may also need to fetch data from databases, APIs, or other services. This is essential for pages that rely on dynamic content. Once the server retrieves this data, it passes it to the React components, allowing them to render with the latest information. This process is known as data fetching.
- Send Fully Rendered HTML to the Client:
- Once the server has fully rendered the HTML for the requested page, it sends the HTML content back to the client. This HTML includes all the necessary tags, such as meta tags, styles, and pre-rendered content. Since the HTML is pre-rendered, the user sees the content immediately after the browser receives the response.
- Browser Receives HTML and Renders the Page:
- The browser receives the fully formed HTML from the server and immediately renders the content to the screen. At this point, the user can see the content of the page, but it might not be interactive yet.
- Hydration Process on the Client Side:
- After rendering the static HTML, the browser downloads the necessary JavaScript files and runs them. React uses a process called hydration to attach event handlers and make the page interactive. Hydration involves React taking over the already-rendered HTML on the client side and binding it with JavaScript functionalities, such as button clicks, form submissions, and dynamic updates.
- Subsequent Client-Side Interactions:
- After hydration, all subsequent interactions (like clicking buttons, submitting forms, etc.) are handled by React on the client side. This is where the Single Page Application (SPA) experience comes in; the page does not reload on subsequent interactions, and React takes care of dynamically updating the content.
How SSR Differs from Client-Side Rendering (CSR)
In Client-Side Rendering (CSR), the browser initially receives a minimal HTML file and must download the JavaScript bundle to render the page content. This process can lead to slower initial load times, especially on slow networks or devices, as the JavaScript must be parsed and executed before any content appears.
In contrast, Server-Side Rendering (SSR) provides a fully rendered HTML page right away. Users get to see content faster without waiting for JavaScript execution. However, the trade-off is that SSR can increase the load on the server, as it must render pages for each request.
Real-World Example of SSR Workflow in React
Consider an online news website using SSR with React:
- A user visits the /latest-news page.
- The server receives the request and runs the React components associated with the “Latest News” page.
- The server fetches the latest news articles from a database or API.
- It combines the data with React components and renders them to HTML.
- The fully rendered HTML, including the news articles, is sent to the user’s browser.
- The browser displays the news articles almost instantly, providing a better user experience.
- React hydrates the page, enabling features like article filtering or sorting to work without reloading the page.
Purpose of render in React JS
In React, the render method is a fundamental concept that serves as the core mechanism for building user interfaces. It is responsible for describing the structure of the user interface for a particular component. Every React component must have a render method that returns the React elements, which are then used by React to update the Document Object Model (DOM) efficiently.
What is render method ?
The render method is a function that returns a React element, which can be a single element or multiple elements enclosed in a single parent element. The render method is called by React to display the content defined by the component. When the state or props of a component change, the render method is re-invoked, allowing React to compare the newly returned elements with the previous ones and determine the minimal changes required to update the UI.
Key Purposes of the render Method in React
- Defining the Component’s UI:
- The primary purpose of the render method is to define what the user interface (UI) of a component should look like. It describes the component’s appearance by returning a tree of React elements created with JSX (JavaScript XML), a syntax extension for JavaScript.
- Example:
jsxCopy codeclass MyComponent extends React.Component {
render() {
return (
<div>
<h1>Hello, World!</h1>
<p>This is a simple React component.</p>
</div>
);
}
}
In this example, the render method returns a div element containing an h1 and a p element. This structure defines what the component will display when it is rendered.
2. Reflecting Changes in the State or Props:
- When a component’s state or props change, the render method is called again to update the UI. React uses a concept called Virtual DOM to optimize these updates. When the render method is invoked, React creates a new Virtual DOM and compares it with the previous one. Only the differences (or diffs) are applied to the actual DOM, making the update process very efficient.
- Example:
jsxCopy codeclass Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
- In this Counter component, the render method reflects the current state of count. When the user clicks the button, the increment function updates the state, triggering the render method to update the UI with the new count.
3. Reusability and Composition of Components:
- React components can be reused across the application. The render method enables this by allowing developers to define different UIs using reusable components. Components can be composed to create more complex UIs by nesting them within each other.
- Example:
jsxCopy codefunction Header() {
return <h1>My Website</h1>;
}
function Footer() {
return <footer>© 2024 My Website</footer>;
}
class MainComponent extends React.Component {
render() {
return (
<div>
<Header />
<p>Welcome to my website.</p>
<Footer />
</div>
);
}
}
- Here, Header and Footer are simple components reused in the MainComponent to create a full webpage structure.
4. Conditional Rendering:
- The render method allows for conditional rendering based on the component’s state or props. This means that different UIs can be displayed depending on certain conditions.
- Example:
jsxCopy codeclass Login extends React.Component {
constructor(props) {
super(props);
this.state = { isLoggedIn: false };
}
render() {
return (
<div>
{this.state.isLoggedIn ? <h1>Welcome Back!</h1> : <h1>Please Log In</h1>}
</div>
);
}
}
5. Reactivity in Data-Driven Applications:
- The render method plays a crucial role in reactivity. It helps in building data-driven applications by ensuring the UI always reflects the most recent state of the data. Whenever there is a change in data, the render method ensures the view is updated accordingly.
Limitations and Rules of the render Method
- Pure Function: The render method should be a pure function, meaning it should not modify the state or interact with the browser (like making API calls or manipulating the DOM directly).
- Single Parent Element: The render method must return a single React element. If multiple elements need to be returned, they must be wrapped in a single parent element or a React fragment (<>…</>).
React Rendering Process
Understanding the React rendering process is crucial for developing efficient and performant React applications. This process encompasses how React builds and updates the user interface (UI) based on changes in state and props. It involves several key stages: initial rendering, updates, and unmounting.
1. Initial Rendering
Initial rendering occurs when a React application first mounts into the DOM. This process is crucial as it sets up the initial UI state of the application.
- Component Creation: When a React component is first created, React initializes it by calling the constructor and setting up the initial state. The constructor method is where you can initialize the state and bind event handlers.
- Render Method Invocation: React then calls the render method of the component. The render method returns the JSX (or React elements) that describe what should be displayed. This output is a virtual representation of the UI.
- Virtual DOM Creation: React creates a Virtual DOM tree based on the output of the render method. The Virtual DOM is an in-memory representation of the real DOM, optimized for performance. React uses this Virtual DOM to efficiently update the actual DOM.
- Reconciliation: The Virtual DOM is compared with the previous Virtual DOM to determine what has changed. This process is known as reconciliation. React calculates the minimal set of changes required to update the real DOM and applies these changes.
- DOM Updates: React updates the actual DOM based on the results of the reconciliation process. The changes are applied in a way that minimizes the impact on performance, ensuring that only the necessary parts of the DOM are updated.
- Component Lifecycle Methods: During the initial rendering, React also calls lifecycle methods such as componentDidMount (in class components) or useEffect with an empty dependency array (in functional components). These methods are typically used for initializing data, making API calls, or setting up subscriptions.
2. Updates
Updates occur when there are changes in the component’s state or props, prompting React to re-render the component to reflect these changes.
- Triggering Updates: Updates can be triggered by various factors, such as user interactions (e.g., button clicks), state changes (setState in class components or state hooks in functional components), or prop changes from parent components.
- Render Method Re-Invocation: When an update is triggered, React calls the render method again to get the updated JSX. This new JSX represents the component’s UI after the update.
- Virtual DOM Diffing: React generates a new Virtual DOM tree based on the updated JSX. It then compares this new Virtual DOM tree with the previous one to identify changes. This diffing algorithm efficiently determines which parts of the DOM need to be updated.
- Reconciliation and DOM Updates: Similar to the initial render, React applies the minimal set of changes required to update the actual DOM based on the results of the reconciliation process. This ensures that the UI reflects the latest state or props without unnecessary re-renders.
- Lifecycle Methods and Effects: For updates, React calls lifecycle methods such as componentDidUpdate (in class components) or useEffect with dependencies (in functional components). These methods allow you to perform additional actions or clean up after the component has updated.
3. Unmounting
Unmounting is the process that occurs when a component is removed from the DOM. This is less common but important for cleaning up resources and avoiding memory leaks.
- Component Removal: When a component is removed from the DOM (e.g., due to a change in route or conditional rendering), React performs the unmounting process.
- Cleanup Operations: React calls the componentWillUnmount lifecycle method (in class components) or the cleanup function returned by useEffect (in functional components). This is where you can clean up resources such as timers, subscriptions, or event listeners that were set up in the component.
- Resource Management: Properly handling unmounting ensures that resources are released and memory is managed effectively, preventing potential memory leaks and performance issues.
4. Special Considerations
- React Fiber: React’s reconciliation algorithm is powered by a system called React Fiber, introduced in React 16. Fiber allows React to break down rendering work into units of work, enabling more efficient rendering and better handling of asynchronous updates.
- Concurrent Rendering: React 18 introduced Concurrent Rendering, which allows React to pause and resume rendering work, improving responsiveness and user experience. Concurrent Rendering enables features like Suspense and Concurrent Mode, which provide better handling of asynchronous data and UI updates.
- Suspense and Error Boundaries: Suspense allows components to “wait” for something before rendering, such as data or code splitting. Error Boundaries are used to catch JavaScript errors anywhere in the component tree, preventing crashes and providing fallback UI.
Types of Rendering in React JS ?
1. Client-Side Rendering (CSR)
Client-Side Rendering (CSR) is the most common type of rendering in React applications. In CSR, the browser downloads a minimal HTML page and the JavaScript bundle that contains the React application. The React application is then responsible for rendering the content in the browser.
How CSR Works:
- Initial Load: When a user navigates to a React application, the server serves a basic HTML file that includes the JavaScript bundle.
- JavaScript Execution: The browser loads and executes the JavaScript bundle, which initializes the React application.
- Rendering: React mounts the application into the DOM and starts rendering components based on the initial state and props.
- Dynamic Updates: After the initial load, React manages dynamic updates on the client side. Subsequent interactions are handled by React without reloading the page.
2. Server-Side Rendering (SSR)
Server-Side Rendering (SSR) involves rendering the React components on the server and sending the fully rendered HTML to the client. This approach provides faster initial load times and improved SEO.
How SSR Works:
- Initial Request: When a user requests a page, the server processes the request and generates the HTML by rendering React components.
- Data Fetching: The server may also fetch data required for the page before rendering it.
- HTML Response: The server sends the fully rendered HTML to the client, which is displayed immediately by the browser.
- Hydration: After receiving the HTML, the browser loads and executes the JavaScript bundle to make the page interactive. React hydrates the static HTML, enabling client-side functionality.
3. Static Site Generation (SSG)
Static Site Generation (SSG) involves generating static HTML pages at build time. The generated pages are served as static files from a content delivery network (CDN), providing fast load times and low server costs.
How SSG Works:
- Build Time: During the build process, the application generates static HTML pages based on the component templates and data.
- Deployment: The generated static HTML files are deployed to a CDN or web server.
- User Request: When a user requests a page, the static HTML file is served directly from the CDN or server, resulting in very fast load times.
4. Incremental Static Regeneration (ISR)
Incremental Static Regeneration (ISR) is a feature of Next.js that combines the benefits of static site generation with the ability to update static content incrementally. It allows pages to be updated after the site has been built and deployed.
How ISR Works:
- Initial Build: Pages are initially generated as static HTML during the build process.
- On-Demand Updates: Pages can be updated in the background while serving the static content. ISR enables revalidation of static pages based on a defined interval or specific conditions.
- User Request: When a user requests a page, the static content is served, and if an update is available, it will be applied in the background for subsequent requests.
5. Hybrid Rendering
Hybrid Rendering involves using a combination of CSR, SSR, SSG, and ISR to achieve optimal performance and flexibility. React and Next.js provide the ability to mix different rendering approaches within the same application, depending on the specific requirements of each page or component.
How Hybrid Rendering Works:
- Component-Level Choice: Different components or pages within the same application can use different rendering strategies based on their needs.
- Performance Optimization: Hybrid rendering allows developers to optimize performance and user experience by choosing the best rendering approach for each use case.
What is Server-Side Rendering (SSR) in React?
Server-Side Rendering (SSR) in React refers to the technique of rendering React components on the server rather than in the browser. This approach generates the HTML content of the web page on the server side before sending it to the client. The browser then displays this pre-rendered HTML, which allows users to see the content more quickly and improves SEO performance.
Example of SSR in React:
Here’s a basic example of setting up SSR in a React application:
- Server Setup:
javascriptCopy code// server.js
const express = require(‘express’);
const React = require(‘react’);
const ReactDOMServer = require(‘react-dom/server’);
const App = require(‘./App’).default;
const app = express();
app.get(‘*’, (req, res) => {
const appHtml = ReactDOMServer.renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>SSR React App</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script src=”/bundle.js”></script>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log(‘Server is listening on port 3000’);
});
2. Client Side Hydration :
javascriptCopy code// client.js
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import App from ‘./App’;
ReactDOM.hydrate(<App />, document.getElementById(‘root’));
More about Server-side Rendering in React JS
1. How SSR Works
SSR involves several steps to deliver the rendered HTML to the client:
- Initial Request: When a user requests a page from a React application using SSR, the server receives the request and processes it.
- Rendering on the Server: The server uses React to render the components into HTML. This process involves:
- Fetching Data: If the application requires data from APIs or databases, the server fetches this data before rendering the page.
- Rendering Components: React components are rendered to HTML using the ReactDOMServer.renderToString() method. This generates a string of HTML that represents the initial state of the page.
- Sending HTML to Client: The server sends the fully rendered HTML to the client as part of the response.
- Hydration: Once the HTML is received by the browser, React’s JavaScript bundle is loaded. React then “hydrates” the server-rendered HTML by attaching event handlers and making the page interactive. This process involves calling ReactDOM.hydrate() to merge the static HTML with client-side React functionality.
2. Benefits of SSR
- Faster Time-to-Content: Since the HTML is pre-rendered on the server, users see the content more quickly compared to client-side rendering, where JavaScript needs to be executed first to generate the HTML.
- Improved SEO: Search engines can index the fully rendered HTML more effectively, leading to better SEO performance. This is crucial for content-heavy sites where search engine visibility is important.
- Better Performance on Slow Networks: SSR can improve performance on slower networks or devices because the initial content is sent as static HTML, reducing the time needed to render content on the client side.
3. Challenges of SSR
- Server Load: Rendering pages on the server can increase server load and resource consumption, especially for high-traffic sites. Each request requires the server to render the page, which can be resource-intensive.
- Complexity: Implementing SSR requires additional setup and configuration compared to client-side rendering. Developers need to handle server-side logic, data fetching, and ensure compatibility between server and client-side code.
- Latency: While SSR improves the initial page load time, it may introduce latency due to server processing time. Optimizing server performance and response times is essential to mitigate this issue.
4. Implementation of SSR in React
Implementing SSR in React involves several key steps:
- Set Up a Server: A Node.js server is commonly used to handle SSR. Libraries like Express can be used to set up the server and handle requests.
- Render React Components: Use ReactDOMServer.renderToString() to render React components to HTML on the server.
- Send HTML Response: The server sends the rendered HTML to the client along with the initial JavaScript bundle.
Hydrate on the Client: Once the client receives the HTML and JavaScript bundle, React hydrates the static HTML to enable client-side functionality.
What is React Server Components?
React Server Components (RSC) represent an innovative feature introduced by React that enables server-side rendering of components with minimal client-side JavaScript. This approach aims to optimize performance by reducing the amount of JavaScript that needs to be sent to the client while still allowing for dynamic and interactive applications.
1. Introduction to React Server Components
React Server Components are designed to improve the efficiency of server-rendered applications by allowing developers to build components that run exclusively on the server. Unlike traditional server-side rendering, which involves sending a full JavaScript bundle to the client, React Server Components focus on sending only the rendered HTML and necessary minimal JavaScript.
Key Characteristics of React Server Components:
- Server-Only Execution: Server Components are executed only on the server. They do not include client-side JavaScript for interactions, reducing the overall bundle size.
- Integration with Client Components: Server Components can be seamlessly integrated with Client Components, allowing developers to combine server-rendered content with interactive client-side features.
- Data Fetching on the Server: React Server Components can fetch data directly on the server, avoiding the need for client-side data fetching and reducing the amount of JavaScript required.
2. How React Server Components Work
The workflow for React Server Components involves several steps:
- Component Creation: Developers create Server Components that are designed to run on the server. These components can perform server-side operations, such as fetching data or rendering static content.
- Rendering on the Server: When a request is made, the server renders Server Components to HTML. This HTML is sent to the client as part of the initial page load.
- Client Integration: Server Components can be combined with Client Components in a React application. Client Components handle interactions and dynamic updates on the client side, while Server Components provide pre-rendered content.
- Hydration: After receiving the HTML, the client-side React application hydrates the page to make interactive Client Components functional.
3. Benefits of React Server Components
- Reduced JavaScript Bundle Size: By executing certain components only on the server, React Server Components help minimize the amount of JavaScript sent to the client. This can lead to faster load times and improved performance, especially on mobile devices.
- Improved Performance: Server Components enable faster initial rendering since the server handles the heavy lifting of data fetching and rendering. This reduces the client-side processing needed to display content.
- Seamless Integration: Server Components can be easily integrated with existing Client Components, allowing developers to build applications that leverage both server-side and client-side rendering.
- Simplified Data Fetching: Data fetching is handled on the server side, which can simplify the development process and reduce the complexity of managing asynchronous data loading on the client.
4. Example of React Server Components
Here’s a basic example of how React Server Components might be used in a React application:
- Server Component:
javascriptCopy code// ServerComponent.server.js
import React from ‘react’;
export default function ServerComponent() {
// Simulate server-side data fetching
const data = fetchDataFromServer();
return (
<div>
<h1>Server Rendered Component</h1>
<p>{data}</p>
</div>
);
}
function fetchDataFromServer() {
// Simulate data fetching
return ‘This is data fetched on the server.’;
}
2. Client Side Hydration :
javascriptCopy code// ClientComponent.js
import React, { useState } from ‘react’;
export default function ClientComponent() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Client Rendered Component</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
<p>Count: {count}</p>
</div>
);
}
3. Integration :
javascriptCopy code// App.js
import React from ‘react’;
import ServerComponent from ‘./ServerComponent.server’;
import ClientComponent from ‘./ClientComponent’;
function App() {
return (
<div>
<ServerComponent />
<ClientComponent />
</div>
);
}
export default App;
In this example, ServerComponent is rendered on the server and sent as HTML to the client, while ClientComponent is rendered on the client and handles user interactions.
Importance of Server-Side Rendering in React
Server-Side Rendering (SSR) in React is a crucial technique in modern web development, particularly in React applications. By rendering pages on the server before sending them to the client, SSR can significantly impact performance, SEO, and user experience.
1. Enhanced Performance
Faster Initial Page Load: One of the primary benefits of SSR is the reduction in the time it takes for users to see content. By rendering the HTML on the server, users receive a fully rendered page on the initial load.
Reduced Time to Interactive: SSR also contributes to a faster Time to Interactive (TTI). Since the initial HTML is fully rendered, users can start interacting with the page more quickly compared to client-side rendering (CSR), where the JavaScript must first build the HTML structure.
Improved Perceived Performance: Rendering pages on the server enhances the perceived performance of your application. Users see content faster, which can improve their overall satisfaction and reduce bounce rates.
2. Better Search Engine Optimization (SEO)
Indexing and Crawling: Search engines like Google prioritize content that is easily accessible and crawlable. With SSR, the server sends fully rendered HTML to search engine bots, making it easier for them to index your content.
Rich Snippets and Meta Tags: SSR allows you to include important meta tags, Open Graph tags, and other SEO-related content directly in the HTML sent to the client.
Consistent Content Delivery: Search engines rely on consistent content delivery to evaluate relevance. By rendering content on the server, you ensure that search engine bots and users see the same content, reducing the risk of discrepancies that might affect SEO performance.
3. Improved User Experience
Instant Content Delivery: With SSR, users receive fully rendered pages immediately, enhancing their overall experience.
Support for Legacy Browsers: SSR provides a way to ensure that your application works well across various browsers, including older ones that might have limited JavaScript support.
Reduced Client-Side Workload: By offloading the rendering process to the server, SSR reduces the amount of work the client has to do.
Server Side Rendering vs Client Side Rendering
Server-Side Rendering :
- Rendering Location: Done on the server.
- Initial Load Time: Faster, as HTML is sent directly to the client.
- JavaScript Load: Reduced, as only necessary JavaScript is sent.
- SEO: Enhanced, as search engines receive fully rendered HTML.
Client-Side Rendering :
- Rendering Location: Done in the browser.
- Initial Load Time: Slower, as JavaScript must build the HTML.
- JavaScript Load: Higher, as the entire JavaScript bundle is sent.
- SEO: May require additional techniques to ensure content is indexed.
Choosing Between SSR and CSR :
The decision to use SSR or CSR depends on the specific needs of your application. SSR is ideal for scenarios where performance and SEO are critical, while CSR may be more suitable for applications that require rich interactivity and real-time updates.
When to Use Server-Side Rendering
Server-Side Rendering (SSR) is a powerful technique in web development, but it’s not always the best choice for every application. Deciding when to use SSR involves evaluating your application’s requirements, performance considerations, SEO needs, and user experience goals.
1. Content-Heavy Websites
Examples:
- News Websites: News websites often have a large amount of content that needs to be indexed by search engines. SSR helps deliver fully rendered pages quickly, improving SEO and user experience.
- Blogs: For blogs with numerous posts, SSR ensures that each post is readily available to search engines and users upon initial load.
Benefits:
- Improved Load Times: Users see the complete content faster, reducing bounce rates.
- Enhanced SEO: Search engines can index content more effectively when it is rendered on the server.
2. E-Commerce Platforms
Examples:
- Product Pages: E-commerce platforms require fast-loading product pages to keep users engaged and facilitate conversions. SSR helps by delivering the product information quickly.
- Category Listings: SSR can speed up the rendering of product categories and filters, providing a better shopping experience.
Benefits:
- Faster Page Loads: Quick loading times can lead to higher conversion rates and improved sales.
- Better SEO: Ensures that product pages are indexed correctly, increasing visibility in search engines.
3. Marketing and Landing Pages
Examples:
- Campaign Landing Pages: Marketing campaigns often rely on landing pages that need to load quickly and be easily indexed. SSR helps by providing pre-rendered content to search engines and users.
- Promotional Content: For promotional content that needs high visibility, SSR ensures that search engines can crawl and index the content effectively.
Benefits:
- Higher Conversion Rates: Faster loading times and better SEO can lead to higher conversion rates for marketing campaigns.
- Increased Visibility: Improved indexing by search engines increases the chances of the page appearing in search results.
4. Applications with Dynamic Content
Examples:
- Dashboards: Applications that provide dynamic dashboards or real-time updates benefit from SSR by delivering an initial static view quickly, followed by client-side updates.
- Social Media Platforms: Social media platforms that handle user-generated content can use SSR for initial content delivery and client-side rendering for dynamic interactions.
Benefits:
- Faster Initial Load: Users see initial content quickly, while dynamic updates are handled on the client side.
- Better User Experience: Reduces the time users spend waiting for content to load, improving overall satisfaction.
5. Projects Requiring SEO Optimization
Examples:
- Content Marketing Sites: Sites focused on content marketing need strong SEO to attract organic traffic. SSR provides a fully rendered HTML page for search engines to index.
- Business Websites: Websites for businesses that rely on local search visibility benefit from SSR by ensuring their content is indexed effectively.
Benefits:
- Enhanced Search Engine Visibility: Fully rendered HTML helps search engines index content more accurately.
- Improved Search Rankings: Better indexing can lead to higher search rankings and increased organic traffic.
6. Cases Where SSR May Not Be Ideal
Examples:
- Highly Interactive Applications: Applications that rely heavily on client-side interactivity, such as single-page applications (SPAs) with complex user interactions, may not benefit as much from SSR.
- Real-Time Data: Applications that rely on real-time data updates may find SSR less effective since the server-rendered content may become outdated quickly.
Considerations:
- Increased Complexity: Implementing SSR can add complexity to your application’s architecture and development process.
Server Resources: SSR requires additional server resources for rendering pages, which may impact hosting costs.
Benefits of Server-Side Rendering
- Faster Initial Load: SSR generates the HTML on the server, allowing users to see the content faster when they first visit a page.
- Improved SEO: Search engines can index server-rendered pages more easily, which can help improve your website’s search engine ranking.
- Better Performance for Users: SSR can enhance the performance of websites, especially for users with slower devices or unstable internet connections.
- Enhanced User Experience: By delivering a fully-rendered page from the server, users see content quickly without having to wait for JavaScript to load.
- Reduced Time to Interactive: With SSR, the time it takes for a page to become interactive can be shorter, leading to a smoother user experience.
- Consistent Performance Across Browsers: SSR ensures that the page renders consistently across different browsers, reducing the risk of browser-specific issues.
- Easier Debugging: Server-rendered content is easier to debug because the HTML is generated on the server, making it simpler to track down issues.
- Better Accessibility: Since the content is rendered on the server, users with disabilities who rely on screen readers or other assistive technologies benefit from immediate content visibility.
Server-Side Rendering Pros and Cons
Server-Side Rendering (SSR) offers a variety of benefits but also comes with its own set of challenges. Understanding the pros and cons of SSR helps developers make informed decisions about whether it’s the right approach for their applications.
Pros:
- Faster Initial Page Load: Pages are fully rendered on the server, so users see content faster when they first visit.
- Improved SEO: Search engines can easily index server-rendered pages, which helps with better search rankings.
- Better Performance on Slow Devices: Offloads rendering to the server, reducing the processing burden on client devices.
- Enhanced User Experience: Users get a fully-rendered page quickly without waiting for JavaScript to load.
- Consistent Cross-Browser Performance: Ensures that pages render consistently across different browsers.
- Easier Debugging: The server-side HTML is easier to inspect and debug compared to client-rendered content.
- Improved Accessibility: Content is available to users with disabilities as soon as the page loads.
Cons:
- Increased Server Load: The server handles all the rendering, which can increase its workload and resource usage.
- Slower Subsequent Navigation: Client-side interactions and navigation can be slower since they often require additional server requests.
- Complex Deployment: SSR can require more complex server setup and deployment compared to client-side rendering.
- Less Interactivity: Initial content may be static and less interactive compared to client-side rendered applications.
- Potential for Slower Development: Development might be slower due to the need to manage both server-side and client-side code.
- Caching Challenges: Managing cache effectively can be more complicated, as dynamic content needs to be handled carefully.
How to Implement Server-Side Rendering in React
Implementing Server-Side Rendering (SSR) in React involves rendering components on the server and sending the fully rendered HTML to the client. This process can significantly enhance the performance and SEO of your application.
1. Setting Up Your Project
1.1. Create a New React Application
To begin, you’ll need a React application. If you don’t already have one, you can create it using Create React App (CRA) or another boilerplate setup. For SSR, CRA might not be ideal, so using a custom setup or Next.js is recommended.
1.2. Install Required Packages
For a custom React SSR setup, you’ll need additional packages. Here’s a basic list of what you might need:
- Express: A web server framework for Node.js.
- React-DOM: Provides server-side rendering capabilities.
- React: The core React library.
Install these packages using npm or yarn:
bashCopy codenpm install express react react-dom
or
bashCopy codeyarn add express react react-dom
1.3. Set Up a Basic Express Server
Create an index.js file for your server:
javascriptCopy codeconst express = require(‘express’);
const React = require(‘react’);
const ReactDOMServer = require(‘react-dom/server’);
const App = require(‘./src/App’); // Your main App component
const app = express();
app.get(‘*’, (req, res) => {
const appHtml = ReactDOMServer.renderToString(React.createElement(App));
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React SSR</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script src=”/bundle.js”></script>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log(‘Server is listening on port 3000’);
});
2. Implementing SSR
2.1. Creating a Basic React Component
Create a simple React component that you want to render server-side. For example, App.js:
javascriptCopy codeimport React from ‘react’;
const App = () => (
<div>
<h1>Hello, Server-Side Rendering!</h1>
</div>
);
export default App;
2.2. Rendering on the Server
In the index.js file of your server setup, you use ReactDOMServer.renderToString to render your React component to a string. This method converts your React component into an HTML string that can be sent to the client.
2.3. Sending HTML to the Client
The server setup shown above sends the rendered HTML as part of the response. The HTML includes the fully rendered content, which improves the initial load time and SEO.
3. Handling Client-Side Hydration
3.1. Creating a Client-Side Entry Point
You need a client-side entry point to rehydrate your server-rendered HTML. Create a client.js file:
javascriptCopy codeimport React from ‘react’;
import ReactDOM from ‘react-dom’;
import App from ‘./src/App’;
ReactDOM.hydrate(<App />, document.getElementById(‘root’));
3.2. Bundling Your Client-Side Code
Use a bundler like Webpack to bundle your client-side code. Ensure that client.js is included in your bundle and referenced in the server-rendered HTML.
3.3. Including the Bundle in Your HTML
Ensure the <script src=”/bundle.js”></script> tag in your server response points to the bundled client-side code.
4. Implementing Routing
4.1. Setting Up React Router
To handle routing with SSR, you need to set up React Router. Install the required packages:
bashCopy codenpm install react-router-dom
4.2. Configuring Routing on the Server
Update your server to handle different routes:
javascriptCopy codeconst { StaticRouter } = require(‘react-router-dom/server’);
app.get(‘*’, (req, res) => {
const context = {};
const appHtml = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React SSR</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script src=”/bundle.js”></script>
</body>
</html>
`);
});
4.3. Handling Routing on the Client
Ensure your client-side routing matches the server-side routing by using BrowserRouter in client.js:
javascriptCopy codeimport { BrowserRouter } from ‘react-router-dom’;
ReactDOM.hydrate(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById(‘root’)
);
5. Data Fetching and Hydration
5.1. Fetching Data on the Server
For SSR, you may need to fetch data on the server before rendering. Modify your server code to handle data fetching:
javascriptCopy codeapp.get(‘*’, async (req, res) => {
const data = await fetchDataFromAPI();
const context = {};
const appHtml = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App initialData={data} />
</StaticRouter>
);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React SSR</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script>window.__INITIAL_DATA__ = ${JSON.stringify(data)}</script>
<script src=”/bundle.js”></script>
</body>
</html>
`);
});
5.2. Hydrating Data on the Client
On the client side, use the initial data to hydrate your app:
javascriptCopy codeconst initialData = window.__INITIAL_DATA__;
ReactDOM.hydrate(
<BrowserRouter>
<App initialData={initialData} />
</BrowserRouter>,
document.getElementById(‘root’)
);
6. Advanced SSR Techniques
6.1. Code Splitting
Use dynamic imports and Webpack’s code splitting to load only the necessary code for each route. This can be combined with SSR to improve performance:
javascriptCopy codeconst LazyComponent = React.lazy(() => import(‘./LazyComponent’));
const App = () => (
<Suspense fallback={<div>Loading…</div>}>
<LazyComponent />
</Suspense>
);
6.2. Server-Side Caching
Implement caching strategies to store and serve pre-rendered pages. Use cache headers and server-side caching mechanisms to improve performance.
6.3. Error Handling and Fallbacks
Handle errors gracefully on the server and client. Ensure that your application can recover from errors and provide meaningful fallback content.
Server-Side Rendering with Examples:
Server-Side Rendering (SSR) can significantly enhance the performance and SEO of your React application. To illustrate how SSR works in practice, let’s explore some concrete examples, demonstrating the implementation of SSR with different setups and use cases.
1. Basic Example with Express and React
In this example, we’ll use a simple setup with Express and React to render a static page on the server.
1.1. Setting Up the Project
Start by creating a new directory for your project and initialize it:
bashCopy codemkdir react-ssr-example
cd react-ssr-example
npm init -y
Install the necessary dependencies:
bashCopy codenpm install express react react-dom
Create the following directory structure:
cssCopy codereact-ssr-example/
│
├── src/
│ ├── App.js
│ └── index.js
│
├── server/
│ └── server.js
│
├── package.json
└── .gitignore
1.2. Create the React Component
In src/App.js, define a simple React component:
javascriptCopy codeimport React from ‘react’;
const App = () => (
<div>
<h1>Welcome to SSR with React!</h1>
</div>
);
export default App;
1.3. Create the Express Server
In server/server.js, set up the Express server to handle SSR:
javascriptCopy codeconst express = require(‘express’);
const React = require(‘react’);
const ReactDOMServer = require(‘react-dom/server’);
const App = require(‘../src/App’).default; // Import your React component
const app = express();
app.get(‘*’, (req, res) => {
const appHtml = ReactDOMServer.renderToString(React.createElement(App));
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React SSR Example</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script src=”/bundle.js”></script>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log(‘Server is listening on port 3000’);
});
1.4. Bundle Client-Side Code
Use Webpack to bundle your client-side code. Create a webpack.config.js file in the root directory:
javascriptCopy codeconst path = require(‘path’);
module.exports = {
entry: ‘./src/index.js’,
output: {
path: path.resolve(__dirname, ‘dist’),
filename: ‘bundle.js’,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ‘babel-loader’,
},
],
},
};
Create src/index.js for client-side rendering:
javascriptCopy codeimport React from ‘react’;
import ReactDOM from ‘react-dom’;
import App from ‘./App’;
ReactDOM.hydrate(<App />, document.getElementById(‘root’));
Run Webpack to generate the bundle:
bashCopy codenpx webpack
Start Your Server :
bashCopy codenode server/server.js
2. Example with Data Fetching
In this example, we’ll fetch data on the server before rendering the component. This demonstrates how to integrate data fetching with SSR.
2.1. Modify the React Component
Update src/App.js to accept data as props:
javascriptCopy codeimport React from ‘react’;
const App = ({ data }) => (
<div>
<h1>Server-Side Data Fetching</h1>
<p>{data.message}</p>
</div>
);
export default App;
2.2. Fetch Data on the Server
Modify server/server.js to fetch data before rendering:
javascriptCopy codeconst express = require(‘express’);
const React = require(‘react’);
const ReactDOMServer = require(‘react-dom/server’);
const App = require(‘../src/App’).default;
const app = express();
const fetchData = async () => {
// Simulate data fetching
return { message: ‘Hello from the server!’ };
};
app.get(‘*’, async (req, res) => {
const data = await fetchData();
const appHtml = ReactDOMServer.renderToString(React.createElement(App, { data }));
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>SSR with Data Fetching</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script src=”/bundle.js”></script>
<script>window.__INITIAL_DATA__ = ${JSON.stringify(data)}</script>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log(‘Server is listening on port 3000’);
});
2.3. Hydrate Data on the Client
Modify src/index.js to use the initial data:
javascriptCopy codeimport React from ‘react’;
import ReactDOM from ‘react-dom’;
import App from ‘./App’;
const initialData = window.__INITIAL_DATA__;
ReactDOM.hydrate(<App data={initialData} />, document.getElementById(‘root’));
3. Example with React Router
This example demonstrates SSR with React Router for handling different routes.
3.1. Install React Router
Install React Router and related packages:
bashCopy codenpm install react-router-dom @babel/preset-env @babel/preset-react babel-loader
3.2. Set Up Routing in React
Create a simple routing setup in src/App.js:
javascriptCopy codeimport React from ‘react’;
import { BrowserRouter, Route, Switch } from ‘react-router-dom’;
const Home = () => <h2>Home Page</h2>;
const About = () => <h2>About Page</h2>;
const App = () => (
<BrowserRouter>
<Switch>
<Route exact path=”/” component={Home} />
<Route path=”/about” component={About} />
</Switch>
</BrowserRouter>
);
export default App;
3.3. Set Up Routing on the Server
Modify server/server.js to handle routing:
javascriptCopy codeconst express = require(‘express’);
const React = require(‘react’);
const ReactDOMServer = require(‘react-dom/server’);
const { StaticRouter } = require(‘react-router-dom/server’);
const App = require(‘../src/App’).default;
const app = express();
app.get(‘*’, (req, res) => {
const context = {};
const appHtml = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React SSR with Routing</title>
</head>
<body>
<div id=”root”>${appHtml}</div>
<script src=”/bundle.js”></script>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log(‘Server is listening on port 3000’);
});
3.4. Update Client-Side Routing
Ensure src/index.js uses BrowserRouter:
javascriptCopy codeimport React from ‘react’;
import ReactDOM from ‘react-dom’;
import { BrowserRouter } from ‘react-router-dom’;
import App from ‘./App’;
ReactDOM.hydrate(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById(‘root’)
);
4. Example with Next.js
Next.js is a popular framework for React that supports SSR out of the box. Here’s a basic example of using Next.js.
4.1. Create a New Next.js Project
Install Next.js and create a new project:
bashCopy codenpx create-next-app@latest my-next-app
cd my-next-app
4.2. Create a Simple Page
In pages/index.js, create a simple page:
javascriptCopy codeexport default function Home()
{
return <h1>Welcome to Next.js with SSR!</h1>;
}
4.3. Run the Application
Start the Next.js development server:
bashCopy codenpm run dev
Visit http://localhost:3000 to see the server-rendered page.
4.4. Fetch Data in Next.js
Next.js supports data fetching with getServerSideProps:
javascriptCopy codeexport async function getServerSideProps()
{
// Simulate data fetching
const data = { message: ‘Hello from Next.js!’ };
return { props: { data } };
}
export default function Home({ data })
{
return <h1>{data.message}</h1>;
}
React SSR Frameworks
React Server-Side Rendering (SSR) can be achieved using various frameworks and libraries that simplify the process and provide additional features. In this section, we’ll explore some popular SSR frameworks for React, their features, and how they enhance the SSR experience.
1. Next.js
1.1. Overview
Next.js is a widely used React framework that provides built-in support for Server-Side Rendering (SSR), Static Site Generation (SSG), and Incremental Static Regeneration (ISR). It offers a robust set of features that streamline development and improve performance.
1.2. Key Features
- File-Based Routing: Automatic routing based on the file structure in the pages directory.
- API Routes: Built-in support for API routes, allowing you to build serverless functions directly within your Next.js app.
- Automatic Code Splitting: Code is split automatically, reducing the amount of JavaScript that needs to be loaded on each page.
- Image Optimization: Optimizes images with built-in components that handle image loading and resizing.
1.3. Example Setup
Creating an SSR-enabled application with Next.js is straightforward:
- Install Next.js:
bashCopy codenpx create-next-app@latest my-next-app
cd my-next-app
2. Create a page with SSR:
javascriptCopy code// pages/index.js
export async function getServerSideProps()
{
// Fetch data on the server
const res = await fetch(‘https://api.example.com/data’);
const data = await res.json();
return {
props: { data }, // Will be passed to the page component as props
};
}
export default function HomePage({ data }) {
return (
<div>
<h1>Server-Side Data Fetching</h1>
<p>{data.message}</p>
</div>
);
}
3. Start the development server:
bashCopy codenpm run dev
1.4. When to Use
Use Next.js when you need a full-featured framework that supports SSR, SSG, and API routes out of the box. It’s ideal for building production-ready React applications with optimized performance and SEO.
2. Remix
2.1. Overview
Remix is another powerful framework for React that focuses on providing a great developer experience while leveraging server-side rendering to enhance performance and SEO.
2.2. Key Features
- Nested Routes: Supports nested routing, allowing you to load data and components at different levels.
- Data Loading: Built-in support for loading data on the server and client, with support for loaders at different levels of your app.
- Error Boundaries: Handles errors at various levels, improving resilience and user experience.
2.3. Example Setup
Here’s a basic example of using Remix:
- Install Remix:
bashCopy codenpx create-remix@latest
2. Create a page with SSR:
javascriptCopy code// app/routes/index.jsx
import { json, LoaderFunction } from ‘remix’;
export let loader: LoaderFunction = async () =>
{
const res = await fetch(‘https://api.example.com/data’);
const data = await res.json();
return json(data);
};
export default function IndexPage() {
let data = useLoaderData();
return (
<div>
<h1>Server-Side Data Fetching with Remix</h1>
<p>{data.message}</p>
</div>
);
}
3. Start the Development Server :
bashCopy codenpm run dev
2.4. When to Use
Remix is a great choice if you want a framework that emphasizes server-side rendering and data loading while providing a modern developer experience. It’s well-suited for applications with complex routing and data needs.
3. Razzle
3.1. Overview
Razzle is a framework that abstracts the setup of server-side rendering for React applications, offering a zero-config approach similar to Create React App but for SSR.
3.2. Key Features
- Zero Config: Provides a default configuration for SSR, making it easy to get started.
- Customizable: Allows customization of Webpack and Babel configurations as needed.
- Universal Code: Supports universal (isomorphic) JavaScript, allowing code to run on both the client and server.
3.3. Example Setup
Here’s a basic example using Razzle:
- Install Razzle:
bashCopy codenpx create-razzle-app my-razzle-app
cd my-razzle-app
2. Create a simple SSR component :
javascriptCopy code// src/App.js
import React from ‘react’;
const App = () => (
<div>
<h1>Hello from Razzle!</h1>
</div>
);
export default App;
3. Start the development Server :
bashCopy codenpm start
3.4. When to Use
Razzle is ideal for developers who want a simple way to set up server-side rendering with minimal configuration. It’s well-suited for projects where you want the benefits of SSR without extensive setup.
4. After.js
4.1. Overview
After.js is a framework that combines features from React, Next.js, and Razzle to provide a flexible SSR solution for React applications.
4.2. Key Features
- Dynamic Routing: Supports dynamic routes and data fetching on the server.
- Hot Module Replacement: Provides hot reloading for a better development experience.
- Flexible Configuration: Allows for flexible configuration and integration with various data sources.
4.3. Example Setup
Here’s a basic example using After.js:
- Install After.js:
bashCopy codenpx create-after-app my-after-app
cd my-after-app
2. Creat Simple SSR Page :
javascriptCopy code// pages/index.js
import React from ‘react’;
const HomePage = ({ data }) => (
<div>
<h1>Welcome to After.js</h1>
<p>{data.message}</p>
</div>
);
export async function getServerSideProps()
{
const res = await fetch(‘https://api.example.com/data’);
const data = await res.json();
return { props: { data } };
}
export default HomePage;
3. Start the Development Server :
bashCopy codenpm start
4.4. When to Use
After.js is suitable for projects that require dynamic routing and SSR with a flexible configuration. It’s a good choice for applications that need more control over SSR and client-side functionality.
Requirements for SSR
Server-Side Rendering (SSR) in React enhances performance and SEO by generating HTML on the server rather than on the client. However, to successfully implement SSR, certain requirements and considerations need to be addressed.
1. Server Infrastructure
1.1. Web Server
You need a web server capable of handling server-side rendering. Popular choices include:
- Node.js: Often used with Express.js or other frameworks to handle SSR for React applications.
- Nginx: Can be used as a reverse proxy server to handle requests and forward them to your Node.js server.
1.2. Hosting
Hosting options include:
- Cloud Providers: Platforms like AWS, Google Cloud, and Azure offer scalable environments suitable for SSR applications.
- Platform-as-a-Service (PaaS): Services like Heroku or Vercel simplify deployment and scaling of SSR applications.
1.3. Server Setup
You need to set up a server that:
- Executes JavaScript: The server should be able to execute JavaScript code, usually through Node.js.
- Handles HTTP Requests: The server should process incoming requests, render pages, and send HTML back to the client.
- Manages State and Data: Ensure the server can fetch and manage data required for rendering pages.
2. Rendering Libraries
2.1. React DOM Server
- Purpose: React provides a library called react-dom/server that includes methods for server-side rendering. The primary method is renderToString(), which generates HTML from React components.
javascriptCopy codeimport React from ‘react’;
import ReactDOMServer from ‘react-dom/server’;
import App from ‘./App’;
const html = ReactDOMServer.renderToString(<App />);
2.2. Additional Libraries
- Express.js: Often used in conjunction with React to handle routing and server-side rendering.
- Redux or Context API: For managing state and passing data between components and the server.
3. Application Code Structure
3.1. Component Structure
- Universal Components: Ensure that components are capable of rendering on both the client and server. Avoid using browser-specific APIs or code that relies on the DOM directly.
- Data Fetching: Implement data-fetching mechanisms that work on both the server and client, such as getServerSideProps in Next.js or custom data-fetching logic.
3.2. Routing
- Server-Side Routes: Set up routes that the server can handle to render specific pages. This may involve configuring route handling in frameworks like Express.js or Next.js.
- Client-Side Routing: Ensure that client-side routing works seamlessly after the initial page load. Libraries like React Router can be used for client-side routing.
4. Configuration
4.1. Environment Configuration
- Environment Variables: Configure environment variables for different environments (development, staging, production) to manage server settings and API endpoints.
- Build Configuration: Ensure that your build setup can handle SSR. This may involve configuring Webpack or other build tools.
4.2. Server-Side Code Execution
- Code Bundling: Use tools like Webpack to bundle server-side code separately from client-side code.
- Code Splitting: Implement code splitting to load only the necessary code on the server and client.
5. Error Handling
5.1. Error Boundaries
- Server-Side Error Handling: Implement error boundaries to catch and handle errors during server-side rendering. This helps prevent crashes and ensures a better user experience.
5.2. Logging
- Server Logs: Set up logging to track errors and performance issues on the server. This can help with debugging and maintaining your SSR application.
6. Performance Considerations
6.1. Caching
- Server-Side Caching: Implement caching mechanisms to reduce the load on your server and improve performance. Tools like Redis can be used for caching server-side data.
6.2. Code Optimization
- Minification: Minify JavaScript and CSS to reduce the size of assets and improve load times.
- Compression: Use Gzip or Brotli compression to reduce the size of the data sent from the server.
7. Security Considerations
7.1. Data Protection
- Sanitization: Ensure that data is properly sanitized to prevent security vulnerabilities like XSS (Cross-Site Scripting).
- HTTPS: Use HTTPS to encrypt data transmitted between the server and client.
7.2. Authentication
- Session Management: Implement secure session management to handle user authentication and authorization.
Render React from String
Rendering React components from a string involves converting HTML or JSX into a React component that can be displayed on the web page. This technique is particularly useful when you need to render components dynamically based on server-generated content or when working with server-side rendering (SSR).
1. What Does “Render React from String” Mean?
Rendering React from a string refers to the process of taking an HTML string or JSX syntax and converting it into a React component that is rendered in the browser. Typically, React relies on JavaScript code to create components, but there are scenarios where the code is generated or fetched as a string. This is where rendering from a string becomes essential.
Examples of When You Might Need This:
- Server-Side Content Rendering: When you fetch pre-rendered HTML content from the server and convert it into React components.
- CMS Integration: When using content from a Content Management System (CMS) where the HTML structure is provided as a string.
- Dynamic Content Rendering: When HTML strings are dynamically generated based on user input or external data sources.
2. Methods for Rendering React from a String
There are primarily two methods for rendering React components from strings:
2.1. dangerouslySetInnerHTML
React provides a property called dangerouslySetInnerHTML that allows you to insert raw HTML strings into a component. This method comes with a warning label because it can introduce cross-site scripting (XSS) vulnerabilities if not used carefully.
Example Usage:
javascriptCopy codeimport React from ‘react’;
const RenderFromString = ({ htmlString }) =>
{
return (
<div dangerouslySetInnerHTML={{ __html: htmlString }} />
);
};
const htmlString = “<div><h1>Hello from a string!</h1><p>This content is rendered from a string.</p></div>”;
const App = () => {
return <RenderFromString htmlString={htmlString} />;
};
export default App;
Key Points:
- Direct Injection: The dangerouslySetInnerHTML prop directly injects the HTML content into the DOM.
- Security Concerns: Be cautious with this method; sanitize any input to avoid XSS attacks.
2.2. Using ReactDOMServer for Server-Side Strings
When working with server-side rendering or when you need to convert HTML strings to React components, ReactDOMServer provides utilities like renderToString() and renderToStaticMarkup() to convert components to HTML strings. You can use these to render server-generated strings back into React components on the client side.
Example Usage:
javascriptCopy codeimport React from ‘react’;
import ReactDOMServer from ‘react-dom/server’;
const MyComponent = () => <h1>Hello from Server-Side Rendering!</h1>;
// Render to an HTML string
const htmlString = ReactDOMServer.renderToString(<MyComponent />);
console.log(htmlString);
Steps Involved:
- Convert Component to String: Use ReactDOMServer.renderToString() to generate an HTML string.
- Inject into Client: Once the HTML string is prepared, inject it into the client-side application using dangerouslySetInnerHTML or by directly inserting it into the DOM.
or want to continue reading Server Side Redering vs Client Side Rendering
Render HTML in React
Rendering HTML in React is a common task when dealing with web development. React components are usually written using JSX, which allows HTML-like syntax in JavaScript. However, there are scenarios where you may need to render raw HTML content directly, such as when you receive HTML from an API, a CMS, or when integrating with third-party libraries.
1. What Does It Mean to Render HTML in React?
In the context of React, “rendering HTML” means displaying HTML content inside a React component. By default, JSX allows you to write HTML-like syntax, but there are cases where HTML strings are fetched from external sources or dynamically generated. React does not automatically render raw HTML strings due to security concerns, so you need specific techniques to display them safely.
2. Common Methods to Render HTML in React
Here are several methods to render HTML content within React components:
2.1. Using JSX Syntax
The most straightforward way to render HTML in React is by writing HTML directly in JSX. This method is clean and ensures that the HTML content is parsed as part of the component’s rendering process.
Example Usage:
javascriptCopy codeimport React from ‘react’;
const SimpleComponent = () => {
return (
<div>
<h1>Hello, World!</h1>
<p>This is rendered using JSX syntax in React.</p>
</div>
);
};
export default SimpleComponent;
Key Points:
- Clean and Safe: This is the default and recommended way of rendering HTML.
- Automatic Sanitization: JSX prevents the injection of malicious content.
2.2. Using dangerouslySetInnerHTML
For scenarios where you receive HTML content as a string from an API, CMS, or user input, you can use React’s dangerouslySetInnerHTML property. This allows you to set the inner HTML of a component directly.
Example Usage:
javascriptCopy codeimport React from ‘react’;
const RenderHtmlContent = ({ htmlString }) => {
return (
<div dangerouslySetInnerHTML={{ __html: htmlString }} />
);
};
const App = () => {
const htmlString = “<h2>Welcome to My Blog</h2><p>This is a paragraph from HTML string.</p>”;
return <RenderHtmlContent htmlString={htmlString} />;
};
export default App;
Step 3: Render the Form Fields
With the initial state and event handler methods in place, you can now render the form fields using JSX. Be sure to bind the value of each form field to the corresponding state property and attach the appropriate event handlers to handle user input. For example:
“`
class MyForm extends React.Component
{
constructor(props)
{
super(props);
this.state = {
username: ”,
password: ”
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
Username:
<input
type=”text”
name=”username”
value={this.state.username}
onChange={this.handleInputChange} />
</label>
<label>
Password:
<input
type=”password”
name=”password”
value={this.state.password}
onChange={this.handleInputChange} />
</label>
<button type=”submit”>Submit</button>
</form>
);
}
}
“`
Key Points:
- Flexibility: This method allows dynamic rendering of HTML content.
- Security Risk: Potentially dangerous if the content is not sanitized, as it can lead to Cross-Site Scripting (XSS) attacks. Always sanitize HTML strings before using them with dangerouslySetInnerHTML.
2.3. Using Libraries to Safely Render HTML
There are libraries like html-react-parser and dompurify that provide safer and more controlled ways to render HTML strings. These libraries help parse HTML and sanitize content, protecting against XSS attacks.
Using html-react-parser:
javascriptCopy codeimport React from ‘react’;
import parse from ‘html-react-parser’;
const RenderWithParser = ({ htmlString }) =>
{
return <div>{parse(htmlString)}</div>;
};
const App = () => {
const htmlString = “<h2>Secure HTML Rendering</h2><p>Using html-react-parser to render HTML safely.</p>”;
return <RenderWithParser htmlString={htmlString} />;
};
export default App;
Key Points:
- Safety: The html-react-parser library provides a secure way to parse and render HTML.
- Flexibility: Offers more control over how the HTML content is parsed and displayed.
Using dompurify for Sanitization:
javascriptCopy codeimport React from ‘react’;
import DOMPurify from ‘dompurify’;
const SafeRender = ({ htmlString }) => {
const cleanHtml = DOMPurify.sanitize(htmlString);
return <didangerouslySetInnerHTML={{ __html: cleanHtml }} />;
};
const App = () => {
const htmlString = “<script>alert(‘XSS’);</script><h1>This is safe content.</h1>”;
return <SafeRender htmlString={htmlString} />;
};
export default App;
Key Points:
- Sanitization: DOMPurify removes potentially malicious scripts and sanitizes HTML strings.
- Secure Rendering: Allows using dangerouslySetInnerHTML securely after sanitizing.
Server-Side Rendering in Angular
Server-Side Rendering (SSR) in Angular is achieved through a framework called Angular Universal. Angular Universal enables developers to render the application on the server, allowing for faster initial load times, better performance on slower networks, and improved SEO capabilities.
1. What is Angular Universal?
Angular Universal is a technology that allows Angular applications to be rendered on the server rather than in the browser. Unlike client-side rendering, where JavaScript code is executed in the user’s browser to build and render the user interface, SSR in Angular generates the full HTML on the server and sends it to the client.
2. How Server-Side Rendering Works in Angular
Here’s a step-by-step breakdown of how SSR works in Angular:
- Request is Made: When a user requests a page, a request is sent to the server.
- Server Compiles the App: Angular Universal takes the request and renders the application on the server.
- HTML is Sent to Browser: The fully rendered HTML page is sent to the user’s browser.
- Client Hydration: After the HTML is loaded in the browser, Angular takes over and makes the page interactive, a process known as hydration.
3. Benefits of Server-Side Rendering in Angular
- Improved SEO: Search engine crawlers can easily read server-rendered pages, improving SEO.
- Faster Load Times: The initial page load is faster because the HTML content is pre-rendered on the server.
- Better User Experience: Users see the content more quickly, reducing bounce rates.
4. Setting Up Server-Side Rendering in Angular
To set up SSR in Angular, you need to use Angular Universal. Here are the steps to implement SSR:
- Install Angular Universal:
bashCopy codeng add @nguniversal/express-engine
2. This command adds Angular Universal to your Angular project and configures the necessary files.
3. Update Server Module: Add server-side routes and modules.
4. Run the SSR Application:
bashCopy codenpm run build:ssr && npm run serve:ssr
5. Challenges and Considerations
While SSR offers numerous benefits, it also comes with some challenges, such as:
- Increased Complexity: Managing code that runs both on the server and client can be complex.
- Server Load: SSR increases the server load because rendering happens on the server.
“`
return (
<form>
<label>
Username:
<input
type=”text”
name=”username”
value={formData.username}
onChange={handleInputChange}
/>
</label>
<label>
Password:
<input
type=”password”
name=”password”
value={formData.password}
onChange={handleInputChange}
/>
</label>
<button type=”submit”>Submit</button>
</form>
);
“`
Server-Side Rendering Patterns
Server-side rendering patterns refer to different strategies for rendering web pages on the server side. These patterns are not specific to any framework or technology; they are general approaches that can be applied across various platforms, including React, Angular, Vue, and more.
1. Different Patterns of SSR
Here are some common SSR patterns:
- Full Page Server-Side Rendering: The entire page is rendered on the server for each request. This is the traditional SSR approach and is suitable for static sites or when SEO is a priority.
- Partial Server-Side Rendering: Only parts of the page are rendered on the server. The rest of the content is rendered on the client side. This is useful for applications that need to balance between performance and SEO.
- Hybrid Rendering: This pattern combines SSR and client-side rendering (CSR). Some components are rendered on the server, while others are rendered on the client. This is a common pattern for modern web applications.
- Static Site Generation (SSG): Pages are pre-rendered at build time rather than runtime. This pattern is similar to SSR but doesn’t involve server rendering on each request. It’s efficient for content-heavy sites.
2. Choosing the Right SSR Pattern
Choosing the right SSR pattern depends on the specific needs of the application:
- For SEO-Heavy Sites: Full page SSR is ideal for websites where SEO is crucial, like blogs, news sites, and e-commerce sites.
- For Performance-Critical Applications: Hybrid or partial SSR is suitable for performance-focused applications where both speed and SEO matter.
- For Content-Driven Sites: SSG is a good choice for sites with lots of static content that rarely changes.
What is Client-Side Rendering (CSR)?
Client-Side Rendering (CSR) is the process where rendering happens in the browser using JavaScript. Unlike SSR, which renders the application on the server and sends the HTML to the client, CSR sends a minimal HTML page with JavaScript that renders the application on the client side.
1. How Does Client-Side Rendering Work?
- Initial HTML Load: When a user accesses a CSR-based website, the server sends a bare HTML file with links to JavaScript files.
- JavaScript Execution: The browser downloads and executes JavaScript files, which render the content dynamically.
- Dynamic Content Rendering: The UI is built and updated as the user interacts with the application.
2. Advantages of CSR
- Rich Interactivity: CSR allows for highly interactive UIs, which are necessary for modern web applications.
- Reduced Server Load: The server only serves static assets like JavaScript, CSS, and HTML.
- Smooth User Experience: Transitions between pages are often faster because the app doesn’t need to reload the entire page.
3. Drawbacks of CSR
- SEO Challenges: Since the content is rendered on the client side, search engines may have difficulty crawling and indexing the site.
- Slower Initial Load: The user sees a blank page until the JavaScript is downloaded and executed.
Is React Client-Side Rendering?
Yes, React is inherently a client-side rendering framework. It is designed to render components on the client side using JavaScript. However, React also supports server-side rendering (SSR) through frameworks like Next.js.
1. How React Works with Client-Side Rendering
React’s CSR workflow involves creating a “virtual DOM” that syncs with the actual DOM in the browser, allowing efficient updates and rendering:
- Component-Based Architecture: React components define how the UI should look and behave.
- State Management: React handles state changes efficiently, ensuring that only the necessary parts of the UI are re-rendered.
2. When to Use React for CSR
React is perfect for building Single Page Applications (SPAs) where you need a highly dynamic user interface with minimal server interaction.
Client vs. Server Side Rendering
Client-Side Rendering (CSR) and Server-Side Rendering (SSR) are two different approaches to rendering web applications.
Feature | Client-Side Rendering (CSR) | Server-Side Rendering (SSR) | ||
Rendering Location | In the browser (client side) | On the server before sending to the browser | ||
Initial Load Time | Slower initial load, faster subsequent loads | Faster initial load, slower subsequent loads | ||
SEO | Not SEO-friendly by default |
| ||
Interactivity | Highly interactive UIs | Limited interactivity before hydration | ||
Use Cases | SPAs, Dashboards, highly interactive apps | Content-heavy sites, e-commerce, blogs |
Choosing Between CSR and SSR
- Use CSR: When building dynamic web applications with high interactivity and low SEO requirements.
- Use SSR: When you need better SEO, faster initial load times, and want to pre-render content on the server.
What is Conditional Rendering in React?
Conditional rendering in React allows components to render differently based on the application’s state or props. It is a core concept in React that helps developers build dynamic and interactive user interfaces.
1. Techniques for Conditional Rendering
- Using Ternary Operators:
javascriptCopy codeconst Greeting = ({ isLoggedIn }) =>
(
isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please log in.</h1>
);
- Using Ternary Operators:
javascriptCopy codeconst Greeting = ({ isLoggedIn }) =>
{
if (isLoggedIn)
{
return <h1>Welcome back!</h1>;
}
return <h1>Please log in.</h1>;
};
- Using Logical && Operators:
javascriptCopy codeconst UserProfile = ({ user }) =>
(
user && <h2>Hello, {user.name}!</h2>
);
2. Use Cases for Conditional Rendering
Conditional rendering is useful for toggling visibility, authentication flows, loading states, and more in React applications.
Introduction to SSR in Next.js
Next.js is a popular React framework that provides built-in support for server-side rendering (SSR), static site generation (SSG), and incremental static regeneration (ISR). Next.js simplifies the SSR process, allowing React developers to build fast and SEO-friendly applications.
1. What Makes Next.js Unique?
- File-Based Routing: Simplifies routing by using the file system as an API.
- SSR Out of the Box: Provides an easy way to implement SSR without complex setup.
- Hybrid Rendering: Supports both SSR and SSG, allowing flexibility in rendering.
2. Setting Up SSR with Next.js
To set up SSR in a Next.js application:
- Install Next.js:
bashCopy codenpx create-next-app@latest
cd your-app
npm run dev
2. Create a page component with getServerSideProps to fetch data at runtime:
javascriptCopy codeexport async function getServerSideProps()
{
const res = await fetch(‘https://api.example.com/data’);
const data = await res.json();
return { props: { data } };
}
export default function Page({ data })
{
return <div>{data.content}</div>;
}
Next.js will render this page on the server and send it to the client on each request.
3. Benefits of SSR with Next.js
- SEO Optimization: Improved search engine visibility.
- Dynamic Content: Fetches data at runtime, suitable for frequently changing content.
4. When to Use SSR in Next.js
Use SSR for pages where content frequently changes or is user-specific, such as dashboards, user profiles, and dynamic listings.
Static Site Generation (SSG) vs. Server-Side Rendering (SSR)
Static Site Generation (SSG) and Server-Side Rendering (SSR) are two popular rendering methods available in frameworks like Next.js. Each has its advantages, use cases, and impact on performance and user experience.
1. What is Static Site Generation (SSG)?
Static Site Generation is a method where the HTML for a website is generated at build time, meaning that each page is pre-rendered and stored as static files. These files are then served to users from a Content Delivery Network (CDN), providing ultra-fast load times.
- How SSG Works:
- During the build process, the site generates static HTML files for all the pages.
- These files are deployed to a server or CDN.
- When a user requests a page, the pre-rendered HTML file is served.
- Advantages of SSG:
- Blazing Fast Load Times: Since files are served from the CDN, there’s no server computation.
- Enhanced Security: No server-side processing means reduced exposure to server-side vulnerabilities.
- Cost-Effective: Fewer server resources are required since everything is served statically.
- Use Cases for SSG:
- Documentation sites, blogs, marketing websites, and e-commerce sites with static content.
2. What is Server-Side Rendering (SSR)?
SSR is a rendering method where the HTML is generated on the server for each request. This is beneficial for pages that need to be dynamically rendered based on user data or other dynamic factors.
- How SSR Works:
- A request is sent to the server.
- The server processes the request and renders the HTML.
- The HTML is sent to the client.
- Advantages of SSR:
- SEO Benefits: Content is ready for search engines to crawl, making it suitable for SEO-heavy websites.
- Dynamic Content Handling: Great for pages that change frequently or are customized for users.
- Use Cases for SSR:
- E-commerce product pages, dashboards, and user profiles that require frequent updates.
Incremental Static Regeneration (ISR) in Next.js
Incremental Static Regeneration (ISR) is a hybrid approach that combines the best of both static site generation and server-side rendering. It allows you to update static content after it has been deployed, without needing to rebuild the entire site.
1. What is ISR and How Does it Work?
ISR enables developers to create or update static pages after the site has been built and deployed. It brings the scalability and speed of static sites with the flexibility of dynamic content updates.
- How ISR Works:
- Static pages are pre-rendered at build time.
- When a user requests a page, Next.js serves the static content.
- Behind the scenes, Next.js regenerates the page if the defined time interval (revalidation period) has elapsed.
- Future requests will get the updated page.
- Benefits of ISR:
- Scalability: Only regenerates pages when needed, reducing server load.
- Fresh Content: Combines fast load times with the ability to serve updated content.
2. Setting Up ISR in Next.js
To implement ISR in Next.js, use the revalidate property in the getStaticProps function:
javascriptCopy codeexport async function getStaticProps()
{
const data = await fetchData();
return {
props: { data },
revalidate: 60, // Revalidate every 60 seconds
};
}
- Example Use Case: Blogs, e-commerce product pages, and content sites that need periodic updates.
Conclusion:
In conclusion, server-side rendering (SSR) and static site generation (SSG) have transformed how developers build web applications, offering a range of benefits from enhanced SEO to faster performance and better user experiences. Next.js, with its flexible rendering methods including Incremental Static Regeneration (ISR), is a powerful tool that provides developers with the choice to pick the right rendering strategy based on their needs.
Whether you’re building a content-heavy website, a dynamic e-commerce platform, or a highly interactive web application, understanding the pros and cons of SSR, SSG, and CSR will guide you in selecting the right approach. And with Next.js, you get a powerful, flexible framework that caters to all these needs and more.
FAQ's (Frequently asked Questions)
Server side Rendering vs Client Side Rendering
SSR renders content on the server for every request, making it ideal for dynamic content, while SSG generates static HTML files at build time, making it perfect for static content with faster load times.
ISR allows you to update static pages after they have been deployed without rebuilding the entire site, providing a balance between the benefits of SSR and SSG.
Next.js applications can be deployed on platforms like Vercel, Netlify, AWS Amplify, and Azure. Vercel offers the most seamless integration, especially with its built-in support for Next.js features.
Alternatives include Gatsby, Nuxt.js, Sapper (SvelteKit), and Remix, each catering to different needs and developer preferences.
Use SSR when your content is dynamic and changes frequently or is customized per user. SSG is best for static sites that require fast load times and don’t change often.
Yes, Next.js is highly SEO-friendly, especially with its SSR and SSG capabilities that allow content to be pre-rendered and indexed effectively by search engines.
- Use Dynamic Imports: Load heavy components only when needed using Next.js’s dynamic imports.
- Optimize Images: Use the next/image component to automatically serve optimized images.
- Leverage Caching: Implement caching strategies to reduce server load and speed up page rendering.
- Code Splitting: Break down your codebase into smaller chunks to improve initial load times.
Yes, Redux can be integrated with Next.js for state management. You can use libraries like next-redux-wrapper to easily set up Redux in a Next.js project, allowing for shared state between server and client-side rendering.
Authentication can be implemented using several methods:
- NextAuth.js: A popular library for handling authentication in Next.js with multiple providers like Google, Facebook, and GitHub.
- Custom JWT Authentication: Implement custom authentication using JSON Web Tokens (JWTs) and manage sessions via cookies.
- OAuth and Third-Party Services: Use services like Auth0 or Firebase Authentication for more secure and scalable authentication solutions.
Next.js provides a built-in API route feature that allows you to create serverless functions within the pages/api directory. These routes are perfect for handling backend logic, such as form submissions, data fetching, and more, without needing a separate backend server.
Middleware in Next.js allows you to run code before a request is processed. It can be used to handle tasks like authentication checks, request logging, or redirects. Middleware is defined in the middleware.ts or middleware.js file at the root of your application.
- Meta Tags and Headers: Use the next/head component to add SEO meta tags and titles.
- Sitemaps: Generate sitemaps using plugins or libraries like next-sitemap.
- Structured Data: Include JSON-LD or other structured data formats to enhance search engine understanding.
- Server-Side Rendering: Ensure important content is rendered server-side to improve crawlability.
While Next.js is primarily for web development, it can be used with frameworks like React Native for Web to create web-compatible components. However, it is more common to use Next.js for Progressive Web Apps (PWAs) that can be added to mobile home screens.
Next.js offers built-in support for internationalization (i18n) through its routing system. You can define multiple locales and provide translations for each page. Libraries like next-translate or react-i18next can be used to further enhance i18n functionality.
next.config.js is a configuration file used in Next.js applications to customize the default behavior of the framework. You can use it to enable Webpack customizations, configure redirects, add environment variables, set up image domains, and manage other advanced settings.
Thanks for going through the topic onImportance of Server side rendering vs Client Side rendering with detailed explanations. Hope this helps you.