Welcome to CodeCrew Infotech

shape shape
Shape Shape Shape Shape
Blog

Part- 1 Top 10 Performance Optimization Techniques in React web app

Introduction:

In today’s fast-paced online world, users expect lightning-fast web experiences. For React developers, this translates to ensuring optimal performance in your dynamic web applications. Don’t worry, as this guide explores 10 advanced strategies to enhance the responsiveness and user engagement of your React application in 2024!

Table of Contents:

1.  Code Splitting
2.  Lazy Loading
3.  Memoization
4.  Windowing or List Virtualization
5.  Server-Side Rendering (SSR) or Static Site Generation (SSG)
6.  React Fragments
7.  Profiling and Performance Monitoring
8.  Efficient State Management
9.  Minimize Bundle Size
10.  Image Optimization


Let’s Get Started:

1.  Code Splitting

What: Breaks down your app's code into smaller bundles, loading only what's necessary for the initial view or user interaction, minimizing initial load time.

Code Splitting is a technique that allows us to break down our React app's code into smaller bundles. Instead of loading the entire codebase at once, we load only what's necessary for the initial view or user interaction. This helps minimize the initial load time, which is crucial for providing users with a faster and more responsive web experience.

Example: Use dynamic imports with React.lazy to load components on demand. Split critical rendering code from non-essential parts.

  import BigComponent from './BigComponent';

  //After Code Splitting with React.lazy

  const BigComponent = React.lazy(() => import('./BigComponent'));


Benefits of Code Splitting:  Implementing Code Splitting in your React projects comes with several benefits.

1.  Faster Initial Load Time: Users get to see and interact with the essential parts of your app more quickly.

2.  Better User Experience: Improved responsiveness leads to an overall better user experience.

3.  Reduced Initial Payload: Smaller initial bundles mean less data transfer and quicker rendering.

4.  Optimized Resource Usage: Efficiently load only what's necessary at any given moment.


2.  Lazy Loading

What: Defers loading of non-critical assets (images, videos) until they're visible in the viewport, improving perceived performance.

Lazy loading is a design pattern in software development where resources or components are loaded into a program's memory only when they are explicitly needed, rather than loading everything at the start. This practice improves efficiency by reducing the initial load time and conserving system resources until the specific items are required for execution. In web development, it's commonly employed for deferred loading of assets such as images, enhancing performance and optimizing user experience.

Example: Certainly! The react-lazy-load-image-component is another library for lazy loading images in React. Here's a simple example using this library:

Package: npm install react-lazy-load-image-component

  import React from 'react';

  import { LazyLoadImage } from 'react-lazy-load-image-component';

  import 'react-lazy-load-image-component/src/effects/blur.css'; // Optional: Add a blur effect for better user experience

 

  const LazyLoadedImage = () => {

    return (

      <div>

        {/* Image before lazy loading */}

        <img

          src="placeholder-image.jpg"  // You can use a small placeholder image here

          alt="Placeholder Image"

          style={{ width: '200px', height: '200px' }}

        />

 

        {/* Lazy loaded image using react-lazy-load-image-component */}

        <LazyLoadImage

          src="big-image.jpg"

          alt="Big Image"

          effect="blur" // Optional: Add a blur effect for better user experience

          style={{ width: '100%', height: 'auto' }}

        />

      </div>

    );

  };

 

  export default LazyLoadedImage;


Benefits of Lazy Loading:  Implementing Lazy Loading in your React projects comes with several benefits.

1.  Faster Initial Page Load: By deferring the loading of non-critical assets such as images and videos until they are visible in the viewport, lazy loading reduces the initial page load time. Users can access and interact with the essential parts of your web application more quickly, leading to a better overall user experience.

2.  Improved User Experience: Lazy loading enhances the responsiveness of a web application. Users experience a smoother and more responsive interface since non-essential content is loaded only when it is needed. This contributes to a better user experience, especially on pages with a large number of media elements.

3.  Reduced Data Transfer and Quicker Rendering: The practice of lazy loading helps in optimizing resource usage by loading only the necessary assets at any given moment. This results in smaller initial bundles, reducing the amount of data transferred over the network. As a result, the rendering process is quicker, and users can interact with the content without unnecessary delays, leading to an improved performance.

3.  Memoization

What: Prevents unnecessary re-renders of components by caching results based on props and state, saving computation power.

Memoization is a technique that comes in handy when we want to avoid unnecessary re-renders of our React components. It works by caching the results of expensive operations or calculated values based on the component's props and state. This caching mechanism helps us save computation power and ensures that components only re-render when absolutely necessary.

Example: Wrap components with React.memo or the useMemo hook to memoize calculated values or expensive operations.

import React, { useState } from 'react';

// Before Memoization

const ExpensiveComponentWithoutMemo = ({ data }) => {

  console.log('Rendering ExpensiveComponentWithoutMemo');

  // Some expensive rendering logic consuming data

  return <div>{data}</div>;

};

// After Memoization with React.memo

const ExpensiveComponentWithMemo = React.memo(({ data }) => {

  console.log('Rendering ExpensiveComponentWithMemo');

 

  // Some expensive rendering logic consuming data

  return <div>{data}</div>;

});

const App = () => {

  const [value, setValue] = useState(0);

 

  return (

    <div>

      <h2>Parent Component</h2>

      <button onClick={() => setValue(value + 1)}>Increment Value</button>

      <h3>Without Memoization</h3>

      <ExpensiveComponentWithoutMemo data={value} />

      <h3>With Memoization</h3>

      <ExpensiveComponentWithMemo data={value} />

    </div>

  );

};

export default App;


In this example,
there are two versions of the ExpensiveComponent:

1.  ExpensiveComponentWithoutMemo: This component does not use React.memo, so it will re-render every time its parent component re-renders, even if the data prop remains the same.

2.  ExpensiveComponentWithMemo: This component utilizes React.memo, which memoizes the component and prevents unnecessary re-renders when the props remain the same. The console logs demonstrate whether the component is re-rendered.

Benefits of Memoization:  Implementing Memoization in your React projects comes with several benefits.

1.  Performance Optimization: Memoization helps optimize performance by preventing unnecessary re-renders of components. When a component is memoized, it only re-renders if its dependencies (props or state) have changed. This reduces the computational overhead associated with rendering, leading to a more efficient application.

2.  Reduction in Repeated Computations: Memoization avoids redundant computations by storing the results of expensive function calls and returning the cached result when the same inputs occur again. In React, memoization prevents unnecessary re-renders of components when their props or state haven't changed, saving processing time and resources.

3.  Improved User Experience: By minimizing re-renders of components, memoization contributes to a smoother and more responsive user interface. Components that don't need to update because their inputs haven't changed won't cause unnecessary visual disruptions. This results in a better user experience, particularly in complex applications where rendering efficiency is crucial.


4.  Windowing or List Virtualization

What: Renders only visible items in long lists, enhancing performance for scrollable content.

Windowing or List Virtualization is a technique used to render only the visible items in a long list, optimizing performance by avoiding the rendering of off-screen elements. A popular library for achieving windowing in React is react-window.

Example: Install the react-window library.

Package: npm install react-window

import React from 'react';

import { FixedSizeList } from 'react-window';

 

const ExampleList = () => {

  // Dummy data for the list

  const data = Array.from({ length: 1000 }, (_, index) => `Item ${index + 1}`);

 

  // Row renderer function for rendering individual items

  const Row = ({ index, style }) => (

    <div style={{ ...style, borderBottom: '1px solid #ddd', padding: '10px' }}>

      {data[index]}

    </div>

  );

 

  return (

    <div style={{ height: '300px', overflow: 'auto' }}>

      {/* FixedSizeList is the virtualized list component */}

      <FixedSizeList

        height={300} // Height of the visible area

        itemCount={data.length} // Total number of items in the list

        itemSize={50} // Height of each individual item

        width={300} // Width of the visible area

      >

        {Row}

      </FixedSizeList>

    </div>

  );

};

 

export default ExampleList;


In this example:

1.  FixedSizeList is a component from react-window that efficiently renders a large list by only rendering the items that are currently visible in the viewport.

2.  The itemCount prop is set to the total number of items in your list.

3.  The itemSize prop is set to the height of each individual item.

4.  The Row function is a custom row renderer that specifies how each item should be rendered.

5.  The list will only render the items that are currently visible in the viewport, making it suitable for long lists without compromising performance. Adjust the dimensions and data according to your specific needs.

Benefits of Windowing or List Virtualization: Implementing Memoization in your React projects comes with several benefits.

1.  Reduced Rendering Overhead: By rendering only the visible items in a list, windowing significantly reduces the rendering overhead associated with displaying long lists of items. This leads to faster initial rendering and improved overall performance, especially in scenarios where a large number of items need to be displayed.

2.  Optimized Memory Usage: Virtualization helps optimize memory usage by rendering only the items that are currently visible on the screen. This means that even for very long lists, the application doesn't need to keep all items in the DOM at once. As a result, the memory footprint of the application is reduced, contributing to better efficiency.

3.  Smoother Scrolling Experience: List virtualization enhances the scrolling experience for users. Rendering only the items within the visible area allows for smoother and more responsive scrolling. Users can navigate through the list without delays caused by rendering every item, creating a more seamless interaction.

5.  Server Side Rendering (SSR) or State Site Generation (SSG)

What: Improves initial page load time and SEO by rendering HTML on the server, reducing client-side JavaScript overhead.

Example: Explore frameworks like Next.js for SSR or Gatsby for SSG in React projects.

Package: npm install next react react-dom

Create a pages Directory:

Move or create your React components inside a pages directory at the root of your project. Files in the pages directory automatically become the routes of your Next.js application.

 - src/

    - components/

    - pages/

       - index.js


Inside the Index.js file:

// pages/index.js

import React from 'react';

const HomePage = ({ time }) => {

  return (

    <div>

      <h1>Hello Next.js!</h1>

      <p>Server time: {time}</p>

    </div>

  );

};

export async function getServerSideProps() {

  // This function runs on the server side during every request

  const time = new Date().toLocaleTimeString();

  // The returned object will be merged with the component's props

  return {

    props: {

      time,

    },

  };

}

export default HomePage;


In this example:

The HomePage component is a simple React component displaying a greeting and the server time.

The getServerSideProps function is a special Next.js function that runs on the server side during every request. It fetches data (in this case, the server time) and passes it as props to the component.

To run the application, add the following script to your package.json file:

"scripts": {

  "dev": "next dev",

  "build": "next build",

  "start": "next start"

 }


Then, run: npm run dev

Visit http://localhost:3000 in your browser, and you should see the rendered page with the server time. This example demonstrates Server-Side Rendering (SSR) where the server dynamically generates the content on each request.

For Static Site Generation (SSG), you can modify the getServerSideProps function to use getStaticProps instead. This will pre-render the page at build time, creating a static HTML file that can be served:

export async function getStaticProps() {

  // This function runs at build time

  const time = new Date().toLocaleTimeString();

 

  return {

    props: {

      time,

    },

  };

}


By making this change, the page will be statically generated during the build process, and the server time will not be recalculated on every request. Static Site Generation is suitable for content that doesn't change frequently and offers improved performance.

Benefits of SSR and SSG: Implementing Server-Side Rendering or Static Site Generation comes with a host of advantages

1.  Faster Initial Page Load Time: Users experience quicker access to your content with pre-rendered HTML.

2.  Improved SEO: Search engines love well-formed HTML, and SSR and SSG deliver just that, boosting your site's SEO performance.

3.  Enhanced User Experience: A faster-loading site means a more enjoyable and responsive experience for your users.

You can continue read part-2: Top-10 Performance Optimization Ways