Shubham Goyal
Likes: 0Views: 0
Date: 22nd May 2025
Author: undefined undefined

Introduction

Web performance is crucial for a good user experience. Large JavaScript bundles can slow down your website, causing users to leave if the site takes too long to load. Code splitting and lazy loading are techniques that help solve this by breaking up your app into smaller parts that load only when needed, improving performance.

    Code-Splitting and Dynamic Imports

    Code splitting means dividing your app into smaller bundles that load as necessary, preventing the need to load everything at once. Without code splitting, a large React app includes all components, libraries, and utilities in a single bundle, which can slow down the initial load. With code splitting, only the code required for the current page is loaded, making the app faster.

    The technology behind code splitting is dynamic import(), which tells your bundler to create separate files. For example:

      javascript
      import('./utils/math').then(mathModule => {
       console.log(mathModule.add(1, 2));
      });
      

      This splits math.js into its own file and loads it only when required. In React, React.lazy is commonly used to handle dynamic imports. It allows you to load a component only when it's needed.

      Why code splitting helps: It avoids sending large JavaScript files initially, speeding up the page load by only loading what's necessary. If you load everything upfront, it results in a slow user experience.

        React.lazy and Suspense

        React.lazy and <Suspense> are tools that allow lazy loading in React. React.lazy loads a component only when it’s rendered, and <Suspense> displays a fallback UI while the component is loading.

        Here’s how you use React.lazy and <Suspense> together:

          javascript
          import React, { Suspense, lazy } from 'react';
          
          const LazyWidget = lazy(() => import('./Widget'));
          
          function App() {
           return (
             <Suspense fallback={<div>Loading widget...</div>}>
               <LazyWidget />
             </Suspense>
           );
          }
          

          In this example, LazyWidget is only loaded when needed. Until the component is fully loaded, React shows a fallback UI (like 'Loading widget...'). Once it's ready, the actual component is rendered.

          Example: Basic Lazy Loading

          Here’s an example of using React.lazy with Suspense:

            javascript
            // Gallery.js
            import React, { Suspense, lazy } from 'react';
            
            const ImageGrid = lazy(() => import('./ImageGrid'));
            
            function Gallery() {
             return (
               <div>
                 <h1>My Photo Gallery</h1>
                 <Suspense fallback={<p>Loading gallery...</p>}>
                   <ImageGrid />
                 </Suspense>
               </div>
             );
            }
            
            export default Gallery;
            

            In this case, the ImageGrid component is loaded only when it’s needed, and the user sees 'Loading gallery...' while it loads.

            How Suspense Works

            When a lazy-loaded component is fetching its code, React suspends rendering. It shows the fallback UI instead of the actual content, and once the code is ready, React renders the real component.

            If multiple lazy-loaded components are inside the same <Suspense> boundary, React will wait for all of them to load before showing the content. However, you can also nest multiple <Suspense> components for more control.

              Real-World Examples of Lazy Loading

              Here are some practical examples of lazy loading in React apps.

                Lazy-Loading Page Components (with React Router

                In React Router, you can lazy-load each page component so that the initial bundle only contains the core parts of the app. For example:

                  javascript
                  import React, { Suspense, lazy } from 'react';
                  import { BrowserRouter, Routes, Route } from 'react-router-dom';
                  
                  const Home = lazy(() => import('./pages/Home'));
                  const About = lazy(() => import('./pages/About'));
                  const Dashboard = lazy(() => import('./pages/Dashboard'));
                  
                  function App() {
                   return (
                     <BrowserRouter>
                       <Suspense fallback={<div>Loading page...</div>}>
                         <Routes>
                           <Route path="/" element={<Home />} />
                           <Route path="about" element={<About />} />
                           <Route path="dashboard" element={<Dashboard />} />
                         </Routes>
                       </Suspense>
                     </BrowserRouter>
                   );
                  }
                  
                  export default App;
                  

                  Each route is loaded only when the user navigates to it, keeping the initial load fast.

                  Lazy-Loading a Modal or Dialog

                  You can lazy-load components like modals that are only used on demand:

                    javascript
                    import React, { Suspense, lazy, useState } from 'react';
                    
                    const ExpensiveModal = lazy(() => import('./ExpensiveModal'));
                    
                    function MyComponent() {
                     const [showModal, setShowModal] = useState(false);
                    
                     return (
                       <div>
                         <button onClick={() => setShowModal(true)}>Open Modal</button>
                         {showModal && (
                           <Suspense fallback={<div>Loading modal...</div>}>
                             <ExpensiveModal onClose={() => setShowModal(false)} />
                           </Suspense>
                         )}
                       </div>
                     );
                    }
                    

                    Here, the modal is only loaded when the user clicks to open it. The fallback UI ('Loading modal...') is shown until the modal is ready.

                    Lazy-Loading a Heavy Third-Party Library

                    Sometimes, you may need to lazy-load heavy third-party libraries:

                      javascript
                      import React, { Suspense, lazy } from 'react';
                      
                      const BigChart = lazy(() => import('charting-library'));
                      
                      function ChartWrapper(props) {
                       return (
                         <Suspense fallback={<div>Loading chart...</div>}>
                           <BigChart data={props.data} />
                         </Suspense>
                       );
                      }
                      

                      This technique ensures that libraries like charting tools are only loaded when the user interacts with the component that requires them.

                      Error Boundaries with Suspense

                      Here’s an example of using React.lazy with Suspense:

                      If a lazy-loaded component fails to load, React will trigger an error. To handle such errors gracefully, wrap lazy components in an error boundary. This ensures that users see a friendly error message instead of a broken app.

                      Example:

                        javascript
                        import React, { Suspense, lazy } from 'react';
                        import MyErrorBoundary from './MyErrorBoundary';
                        
                        const LazyWidget = lazy(() => import('./Widget'));
                        
                        function App() {
                         return (
                           <MyErrorBoundary>
                             <Suspense fallback={<div>Loading widget...</div>}>
                               <LazyWidget />
                             </Suspense>
                           </MyErrorBoundary>
                         );
                        }
                        

                        If the component fails to load, the error boundary will catch the error and display a fallback UI.

                        Practical Tips and Best Practices

                        • Always include a <Suspense> fallback: This ensures the user sees a loading state instead of a blank screen when a component is loading.
                        • Use error boundaries: Handle errors caused by failed lazy-loading so users see a helpful message instead of an app crash.
                        • Split code logically: Split large, rarely used parts of your app to avoid loading unnecessary code. Consider lazy-loading components like modals or pages that aren’t immediately needed.
                        • Preload components when necessary: Sometimes you can preload certain components to improve perceived performance when a user is about to interact with them.

                        Responses (0)

                        Write your response here
                        Shubham Goyal
                        Shubham Goyal.All Rights Reserved