⚡ Code Splitting & Lazy Loading

Performance Optimization ka Complete Guide

React Applications ko Fast aur Efficient Banao

📚 Code Splitting & Lazy Loading Kya Hai?

Code Splitting ek technique hai jisme aap apne application ke code ko chhote-chhote bundles (chunks) mein divide karte ho. Iska matlab hai ki user ko sirf wahi code load hota hai jo use us waqt chahiye, baaki ka code baad mein on-demand load hota hai.

Lazy Loading iska implementation hai jisme components, routes, ya resources ko tab load kiya jata hai jab unki zaroorat ho. Isse initial page load time bahut kam ho jata hai aur application faster feel hoti hai.

🎯 Kyun Zaroori Hai?

  • Faster Initial Load: Kam code = Kam download time = Faster app
  • Better Performance: Browser ko kam JavaScript parse aur execute karna padta hai
  • Improved User Experience: Users ko jaldi content dikhta hai
  • Reduced Bandwidth: Users sirf wahi download karte hain jo use karte hain
  • Better Caching: Individual chunks cache ho sakte hain
70%
Bundle Size Reduction
3x
Faster Load Time
50%
Less Memory Usage
90+
Lighthouse Score
💡 Real-World Impact: Netflix ne code splitting implement karke apni initial load time 50% tak reduce kar di. Amazon ne dekha ki har 100ms ki delay se 1% revenue loss hota hai!

1️⃣ React.lazy & Suspense

React.lazy() ek function hai jo aapko components ko dynamically import karne deta hai. Yeh component tab load hota hai jab woh render hone wala ho. Suspense ek component hai jo loading state handle karta hai jab tak lazy component load nahi ho jata.
// Traditional Import (Eager Loading) import HeavyComponent from './HeavyComponent'; // Lazy Import (On-Demand Loading) const HeavyComponent = React.lazy(() => import('./HeavyComponent')); // Usage with Suspense import { lazy, Suspense } from 'react'; const Dashboard = lazy(() => import('./Dashboard')); const Profile = lazy(() => import('./Profile')); const Settings = lazy(() => import('./Settings')); function App() { return ( <Suspense fallback={<div>Loading...</div>}> <Dashboard /> <Profile /> <Settings /> </Suspense> ); }
🎮 Interactive Demo: React.lazy Loading

Click buttons to simulate lazy loading of components:

No component loaded yet. Click a button to see lazy loading in action!

📊 Loading Stats:
0%
Components Loaded:
0
Total Size:
0 KB
Load Time:
0s
⚠️ Important Points:
• React.lazy sirf default exports ke saath kaam karta hai
• Suspense boundary zaroori hai, warna error aayega
• Server-side rendering (SSR) mein React.lazy directly kaam nahi karta
• Multiple lazy components ek hi Suspense boundary share kar sakte hain

2️⃣ Dynamic Imports

Dynamic Imports JavaScript ka native feature hai jo aapko runtime pe modules import karne deta hai. Yeh import() function use karta hai jo ek Promise return karta hai. React.lazy internally isi ko use karta hai, lekin aap ise directly bhi use kar sakte ho non-component code ke liye.
// Dynamic Import for Components const loadComponent = async () => { const module = await import('./MyComponent'); return module.default; }; // Dynamic Import for Utilities const loadUtility = async () => { const { heavyFunction } = await import('./utils'); return heavyFunction(); }; // Dynamic Import for Libraries const loadChart = async () => { const Chart = await import('chart.js'); return new Chart(ctx, config); }; // Conditional Dynamic Import const loadFeature = async (featureName) => { if (featureName === 'advanced') { const module = await import('./AdvancedFeature'); return module.default; } }; // Error Handling const safeImport = async () => { try { const module = await import('./Module'); return module.default; } catch (error) { console.error('Failed to load module', error); return null; } };
🎮 Interactive Demo: Dynamic Import Scenarios

📊 Chart Library

250 KB

Heavy visualization library

Not Loaded

✏️ Rich Text Editor

180 KB

WYSIWYG editor component

Not Loaded

📄 PDF Viewer

320 KB

PDF rendering library

Not Loaded

🗺️ Map Component

400 KB

Interactive maps library

Not Loaded
💾 Current Bundle Size:
50 KB (Initial)

Click on any module above to dynamically import it

✅ Best Practices:
• Heavy libraries (charts, editors, maps) ko dynamically import karo
• User interaction ke baad load karo (button click, tab switch)
• Prefetching use karo agar aapko pata hai user kya use karega
• Error boundaries implement karo failed imports ke liye

3️⃣ Route-based Code Splitting

Route-based Code Splitting sabse common aur effective approach hai. Isme har route (page) ko alag chunk mein split karte hain. Jab user kisi route pe jata hai, sirf usi route ka code load hota hai. Yeh React Router ke saath bahut achhe se kaam karta hai.
// Route-based Code Splitting with React Router import { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; // Lazy load all route components const Home = lazy(() => import('./pages/Home')); const About = lazy(() => import('./pages/About')); const Dashboard = lazy(() => import('./pages/Dashboard')); const Profile = lazy(() => import('./pages/Profile')); const Settings = lazy(() => import('./pages/Settings')); // Loading component const LoadingFallback = () => ( <div style={{ textAlign: 'center', padding: '50px' }}> <div>Loading...</div> </div> ); function App() { return ( <BrowserRouter> <Suspense fallback={<LoadingFallback />}> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/profile" element={<Profile />} /> <Route path="/settings" element={<Settings />} /> </Routes> </Suspense> </BrowserRouter> ); }
🎮 Interactive Demo: Route-based Splitting
🧭 Navigation:
📍 Current Route: /home

🏠 Home Page

Welcome to the home page! This is loaded on demand.

📦 Loaded Chunks:
main.js
50 KB
home.chunk.js
25 KB
about.chunk.js
20 KB
dashboard.chunk.js
45 KB
profile.chunk.js
30 KB
settings.chunk.js
35 KB
Metric Without Code Splitting With Route-based Splitting Initial Bundle Size 500 KB 150 KB (70% reduction) First Contentful Paint 3.5s 1.2s (65% faster) Time to Interactive 5.2s 2.1s (60% faster) Lighthouse Score 65 92 (42% improvement)

4️⃣ Image Optimization & Lazy Loading

Image Lazy Loading ek technique hai jisme images tab load hoti hain jab woh viewport mein aane wali hoti hain. Images usually sabse bada resource hoti hain web pages mein, toh inhe optimize karna bahut zaroori hai. Modern browsers mein native lazy loading support hai.
// Native Lazy Loading (HTML) <img src="image.jpg" loading="lazy" alt="Description" /> // React Component with Lazy Loading const LazyImage = ({ src, alt }) => { const [isLoaded, setIsLoaded] = useState(false); const [isInView, setIsInView] = useState(false); const imgRef = useRef(); useEffect(() => { const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsInView(true); observer.disconnect(); } }, { threshold: 0.1 } ); if (imgRef.current) { observer.observe(imgRef.current); } return () => observer.disconnect(); }, []); return ( <div ref={imgRef}> {isInView ? ( <img src={src} alt={alt} onLoad={() => setIsLoaded(true)} style={{ opacity: isLoaded ? 1 : 0 }} /> ) : ( <div>Loading...</div> )} </div> ); }; // Progressive Image Loading const ProgressiveImage = ({ placeholder, src, alt }) => { const [imgSrc, setImgSrc] = useState(placeholder); useEffect(() => { const img = new Image(); img.src = src; img.onload = () => { setImgSrc(src); }; }, [src]); return ( <img src={imgSrc} alt={alt} style={{ filter: imgSrc === placeholder ? 'blur(10px)' : 'none', transition: 'filter 0.3s' }} /> ); };
🎮 Interactive Demo: Image Lazy Loading

Click "Load Images" to simulate lazy loading:

Image 1
Not Loaded
Image 2
Not Loaded
Image 3
Not Loaded
Image 4
Not Loaded
Image 5
Not Loaded
Image 6
Not Loaded
📊 Loading Statistics:
0/6
Images Loaded
0 KB
Data Saved
0s
Load Time
💡 Image Optimization Tips:
• Modern formats use karo: WebP, AVIF (fallback ke saath)
• Responsive images: srcset aur sizes attributes
• Proper dimensions set karo to avoid layout shift
• CDN use karo automatic optimization ke liye
• Placeholder images ya blur effect use karo better UX ke liye

5️⃣ Chunk Splitting Best Practices

Chunk Splitting ka matlab hai apne code ko intelligent tareeke se divide karna. Webpack aur modern bundlers automatically yeh karte hain, lekin aap configuration se ise optimize kar sakte ho. Sahi chunking strategy se caching improve hoti hai aur users ko kam data download karna padta hai.
// Webpack Configuration for Chunk Splitting module.exports = { optimization: { splitChunks: { chunks: 'all', cacheGroups: { // Vendor chunk - Third-party libraries vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: 10 }, // Common chunk - Shared code common: { minChunks: 2, priority: 5, reuseExistingChunk: true }, // React chunk - Separate React libraries react: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, name: 'react', priority: 20 } } } } }; // Vite Configuration export default { build: { rollupOptions: { output: { manualChunks: { 'react-vendor': ['react', 'react-dom'], 'router': ['react-router-dom'], 'ui-library': ['@mui/material'] } } } } }; // Magic Comments for Webpack const HeavyComponent = lazy(() => import( /* webpackChunkName: "heavy-component" */ /* webpackPrefetch: true */ './HeavyComponent' ) );
🎮 Interactive Demo: Chunk Strategy Comparison

❌ Poor Strategy

main.bundle.js
850 KB
  • Single large bundle
  • Slow initial load
  • Poor caching
  • Wasted bandwidth

✅ Optimal Strategy

main.js
50 KB
vendors.js
200 KB
home.js
30 KB
dashboard.js
45 KB
chart.js
120 KB
  • Multiple optimized chunks
  • Fast initial load (80 KB)
  • Better caching
  • On-demand loading
📊 Performance Comparison:
Metric Poor Strategy Optimal Strategy Improvement
Initial Load 850 KB 80 KB 90% faster
Parse Time 2.5s 0.3s 88% faster
Cache Hit Rate 20% 85% 325% better
Time to Interactive 4.8s 1.2s 75% faster
✅ Chunking Best Practices:

1. Vendor Chunks: Third-party libraries ko alag chunk mein rakho (rarely change hoti hain)
2. Common Chunks: Shared code ko extract karo to avoid duplication
3. Route Chunks: Har route ko alag chunk (automatic with lazy loading)
4. Size Limits: Chunks ko 200-300 KB se chhota rakho
5. Prefetching: Critical chunks ko prefetch karo
6. Naming: Meaningful chunk names use karo debugging ke liye
⚠️ Common Mistakes:
• Bahut zyada chhote chunks (overhead badh jata hai)
• Vendor chunk mein sab kuch daal dena (better to split by usage)
• Dynamic imports ko ignore karna
• Cache busting strategy na hona
• Bundle analyzer na use karna

🚀 Advanced Techniques

Prefetching & Preloading

Prefetching aur Preloading techniques hain jo future mein zaroorat padne wale resources ko pehle se load kar leti hain. Isse user experience smooth ho jata hai kyunki jab user actually resource use karta hai, woh already loaded hota hai.
// Prefetch - Low priority, load when browser is idle const AdminPanel = lazy(() => import( /* webpackPrefetch: true */ './AdminPanel' ) ); // Preload - High priority, load immediately const CriticalComponent = lazy(() => import( /* webpackPreload: true */ './CriticalComponent' ) ); // Manual Prefetching const prefetchComponent = () => { const link = document.createElement('link'); link.rel = 'prefetch'; link.href = '/static/js/dashboard.chunk.js'; document.head.appendChild(link); }; // Prefetch on hover const handleMouseEnter = () => { import('./HeavyComponent'); }; <button onMouseEnter={handleMouseEnter}> Dashboard </button>

Error Boundaries for Lazy Components

// Error Boundary for handling lazy loading failures class LazyLoadErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { console.error('Lazy loading failed:', error, errorInfo); } render() { if (this.state.hasError) { return ( <div> <h2>Failed to load component</h2> <button onClick={() => window.location.reload()}> Retry </button> </div> ); } return this.props.children; } } // Usage <LazyLoadErrorBoundary> <Suspense fallback={<Loading />}> <LazyComponent /> </Suspense> </LazyLoadErrorBoundary>

Measuring Performance

// Performance monitoring const measureLoadTime = async (componentName) => { const startTime = performance.now(); try { await import(`./components/${componentName}`); const endTime = performance.now(); const loadTime = endTime - startTime; console.log(`${componentName} loaded in ${loadTime}ms`); // Send to analytics analytics.track('component_load', { component: componentName, loadTime: loadTime }); } catch (error) { console.error(`Failed to load ${componentName}`, error); } };

🎯 Interview Questions

Yeh questions aapki Code Splitting & Lazy Loading understanding ko test karenge!

Easy

Q1: React.lazy aur Suspense kya hain? Yeh kaise kaam karte hain?

Answer:

React.lazy(): Ek function hai jo dynamic import ko accept karta hai aur ek React component return karta hai. Yeh component tab load hota hai jab woh pehli baar render hone wala ho.

Suspense: Ek component hai jo lazy components ke loading state ko handle karta hai. Jab tak lazy component load nahi hota, tab tak Suspense apna fallback UI show karta hai.

Working:
1. React.lazy() ek Promise return karta hai
2. Jab component render hota hai, React us Promise ko resolve karta hai
3. Tab tak Suspense fallback show karta hai
4. Promise resolve hone ke baad actual component render hota hai

Example:
const MyComponent = lazy(() => import('./MyComponent'));
<Suspense fallback={<Loading />}><MyComponent /></Suspense>

Important: React.lazy sirf default exports ke saath kaam karta hai.
Easy

Q2: Code splitting se kya benefits milte hain? Real-world example do.

Answer:

Benefits:
1. Faster Initial Load: Kam code download = Faster page load
2. Better Performance: Browser ko kam JavaScript parse karna padta hai
3. Improved Caching: Individual chunks cache ho sakte hain
4. Reduced Bandwidth: Users sirf zaroorat ka code download karte hain
5. Better User Experience: Content jaldi dikhta hai

Real-World Example - E-commerce Site:

Without Code Splitting:
• Initial bundle: 800 KB
• Load time: 4.5 seconds
• User ko sab kuch download karna padta hai (admin panel, checkout, product reviews, etc.)

With Code Splitting:
• Initial bundle: 150 KB (home page)
• Load time: 1.2 seconds
• Admin panel (200 KB) - sirf admin users ke liye load hota hai
• Checkout (100 KB) - sirf jab user checkout pe jaye
• Product reviews (80 KB) - sirf jab user reviews tab khole

Result: 70% faster initial load, better conversion rate!
Medium

Q3: Route-based code splitting aur component-based code splitting mein kya difference hai? Kab kaunsa use karoge?

Answer:

Route-based Code Splitting:
• Har route (page) ko alag chunk mein split karte hain
• User jab route change karta hai tab load hota hai
• Sabse common aur recommended approach
• Natural split point hai application mein

Example:
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));

Component-based Code Splitting:
• Individual heavy components ko split karte hain
• Component jab render hone wala ho tab load hota hai
• Specific use cases ke liye
• Fine-grained control milta hai

Example:
const ChartComponent = lazy(() => import('./Chart'));
const RichTextEditor = lazy(() => import('./Editor'));

Kab Kaunsa Use Karein:

Route-based use karo jab:
• Application mein multiple pages hain
• Clear navigation structure hai
• Har page independent functionality hai
• Starting point chahiye code splitting ke liye

Component-based use karo jab:
• Heavy third-party libraries use kar rahe ho (charts, editors)
• Conditional rendering hai (modals, tabs)
• User interaction ke baad load karna hai
• Route-based splitting ke saath combine karke

Best Practice: Dono ko combine karo - routes ko split karo, aur heavy components ko bhi!
Medium

Q4: Webpack ke splitChunks configuration ko explain karo. Vendor chunks kyun important hain?

Answer:

splitChunks Configuration:
Webpack ka optimization feature hai jo automatically code ko multiple chunks mein divide karta hai based on certain rules.

Key Options:
• chunks: 'all' - All chunks ko split karo (async + sync)
• minSize - Minimum chunk size
• maxSize - Maximum chunk size
• minChunks - Kitni baar use hona chahiye
• cacheGroups - Custom splitting rules

Vendor Chunks Kyun Important Hain:

1. Caching Benefits:
• Third-party libraries rarely change hoti hain
• Ek baar load ho gayi toh cache mein reh sakti hain
• Har deployment pe users ko download nahi karni padti

2. Parallel Loading:
• Browser multiple chunks parallel mein download kar sakta hai
• Vendor chunk aur app chunk simultaneously load ho sakte hain

3. Better Organization:
• Your code aur third-party code separate
• Debugging aur analysis easy ho jata hai

4. Optimal Size:
• Large vendor libraries ko separate rakhne se main bundle chhota rehta hai

Example Configuration:
splitChunks: {
  cacheGroups: {
    vendor: {
      test: /[\\/]node_modules[\\/]/,
      name: 'vendors',
      chunks: 'all',
      priority: 10
    },
    react: {
      test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
      name: 'react',
      priority: 20
    }
  }
}

Result:
• main.js (50 KB) - Your app code
• react.js (120 KB) - React libraries (cached)
• vendors.js (200 KB) - Other libraries (cached)
• Total initial: 370 KB, but 320 KB cached on repeat visits!
Medium

Q5: Prefetching aur Preloading mein kya difference hai? Kab kaunsa use karoge?

Answer:

Prefetching:
• Low priority resource loading
• Browser idle hone pe load hota hai
• Future navigation ke liye
• <link rel="prefetch">

Preloading:
• High priority resource loading
• Immediately load hota hai
• Current page ke liye critical resources
• <link rel="preload">

Detailed Comparison:

Feature Prefetch Preload
Priority Low High
When Browser idle time Immediately
Use Case Future pages Current page
Cache HTTP cache Memory cache

Kab Prefetch Use Karein:
• Next page jo user visit kar sakta hai
• Dashboard link pe hover karne pe
• Login ke baad dashboard prefetch karo
• Analytics se predict karo user kahan jayega

Example:
const Dashboard = lazy(() => import(/* webpackPrefetch: true */ './Dashboard'));

Kab Preload Use Karein:
• Critical fonts jo immediately chahiye
• Above-the-fold images
• Critical CSS
• Hero section resources

Example:
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

⚠️ Warning: Preload ka overuse mat karo, warna bandwidth waste hoga aur actual performance kharab ho jayega!
Hard

Q6: Image lazy loading implement karne ke different approaches kya hain? Intersection Observer API ko detail mein explain karo.

Answer:

Image Lazy Loading Approaches:

1. Native Lazy Loading:
• HTML attribute: loading="lazy"
• Browser built-in support
• Sabse simple approach
• Limited customization
<img src="image.jpg" loading="lazy" alt="Description">

2. Intersection Observer API:
• Modern JavaScript API
• Viewport visibility detect karta hai
• Highly customizable
• Better performance than scroll events

Intersection Observer Detailed Explanation:

Kya Hai:
Ek API jo asynchronously observe karta hai ki ek element viewport mein visible hai ya nahi. Yeh scroll events se better hai kyunki yeh main thread ko block nahi karta.

Kaise Kaam Karta Hai:
1. Observer create karo with callback function
2. Target elements ko observe karo
3. Jab element viewport mein aaye, callback trigger hota hai
4. Callback mein image load karo
5. Observer disconnect karo

Implementation:
const imageObserver = new IntersectionObserver(
  (entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src; // Load actual image
        img.classList.add('loaded');
        observer.unobserve(img); // Stop observing
      }
    });
  },
  {
    root: null, // viewport
    rootMargin: '50px', // Load 50px before visible
    threshold: 0.1 // 10% visible hone pe trigger
  }
);

// Observe all lazy images
document.querySelectorAll('img[data-src]').forEach(img => {
  imageObserver.observe(img);
});

3. React Implementation:
const LazyImage = ({ src, alt }) => {
  const [isLoaded, setIsLoaded] = useState(false);
  const [isInView, setIsInView] = useState(false);
  const imgRef = useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsInView(true);
          observer.disconnect();
        }
      },
      { threshold: 0.1, rootMargin: '100px' }
    );

    if (imgRef.current) {
      observer.observe(imgRef.current);
    }

    return () => observer.disconnect();
  }, []);

  return (
    <div ref={imgRef}>
      {isInView ? (
        <img 
          src={src} 
          alt={alt}
          onLoad={() => setIsLoaded(true)}
          style={{ 
            opacity: isLoaded ? 1 : 0,
            transition: 'opacity 0.3s'
          }}
        />
      ) : (
        <div className="placeholder">Loading...</div>
      )}
    </div>
  );
};

4. Progressive Image Loading:
• Pehle low-quality placeholder load karo
• Phir high-quality image load karo
• Smooth transition effect

Benefits of Intersection Observer:
• No scroll event listeners (better performance)
• Asynchronous (non-blocking)
• Customizable thresholds
• Root margin for early loading
• Multiple elements efficiently observe kar sakta hai

Browser Support: 95%+ modern browsers (polyfill available for older browsers)
Hard

Q7: Production environment mein code splitting failures ko kaise handle karoge? Error boundaries aur retry mechanisms explain karo.

Answer:

Code Splitting Failures Kyun Hoti Hain:
• Network issues (slow/unstable connection)
• Chunk files not found (deployment issues)
• Browser cache issues
• CDN failures
• Version mismatches

Comprehensive Error Handling Strategy:

1. Error Boundary Implementation:
class LazyLoadErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
      hasError: false, 
      error: null,
      retryCount: 0 
    };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, errorInfo) {
    // Log to error tracking service
    console.error('Lazy load failed:', error, errorInfo);
    
    // Send to analytics
    analytics.track('lazy_load_error', {
      error: error.message,
      component: this.props.componentName,
      retryCount: this.state.retryCount
    });
  }

  handleRetry = () => {
    this.setState(prevState => ({
      hasError: false,
      error: null,
      retryCount: prevState.retryCount + 1
    }));
  };

  handleReload = () => {
    window.location.reload();
  };

  render() {
    if (this.state.hasError) {
      return (
        <div className="error-container">
          <h2>Failed to load component</h2>
          <p>{this.state.error?.message}</p>
          
          {this.state.retryCount < 3 ? (
            <button onClick={this.handleRetry}>
              Retry ({this.state.retryCount}/3)
            </button>
          ) : (
            <button onClick={this.handleReload}>
              Reload Page
            </button>
          )}
        </div>
      );
    }

    return this.props.children;
  }
}

2. Retry Mechanism with Exponential Backoff:
const lazyWithRetry = (componentImport, retries = 3, interval = 1000) => {
  return new Promise((resolve, reject) => {
    componentImport()
      .then(resolve)
      .catch((error) => {
        if (retries === 0) {
          reject(error);
          return;
        }

        setTimeout(() => {
          console.log(`Retrying... (${retries} attempts left)`);
          lazyWithRetry(componentImport, retries - 1, interval * 2)
            .then(resolve)
            .catch(reject);
        }, interval);
      });
  });
};

// Usage
const Dashboard = lazy(() => 
  lazyWithRetry(() => import('./Dashboard'))
);

3. Fallback Component Strategy:
const LazyComponentWrapper = ({ 
  importFunc, 
  fallbackComponent: FallbackComponent 
}) => {
  const [Component, setComponent] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    importFunc()
      .then(module => setComponent(() => module.default))
      .catch(err => {
        setError(err);
        // Load fallback
        if (FallbackComponent) {
          setComponent(() => FallbackComponent);
        }
      });
  }, []);

  if (error && !Component) {
    return <ErrorDisplay error={error} />;
  }

  if (!Component) {
    return <LoadingSpinner />;
  }

  return <Component />;
};

4. Version Mismatch Detection:
// Store app version in localStorage
const APP_VERSION = '1.2.3';

const checkVersion = () => {
  const storedVersion = localStorage.getItem('appVersion');
  
  if (storedVersion && storedVersion !== APP_VERSION) {
    // New version deployed, clear cache
    if ('caches' in window) {
      caches.keys().then(names => {
        names.forEach(name => caches.delete(name));
      });
    }
    localStorage.setItem('appVersion', APP_VERSION);
    window.location.reload(true);
  } else {
    localStorage.setItem('appVersion', APP_VERSION);
  }
};

// Call on app initialization
checkVersion();

5. Monitoring & Analytics:
const trackLazyLoadMetrics = (componentName, success, loadTime, error) => {
  // Send to analytics service
  analytics.track('lazy_load_metrics', {
    component: componentName,
    success: success,
    loadTime: loadTime,
    error: error?.message,
    userAgent: navigator.userAgent,
    connection: navigator.connection?.effectiveType,
    timestamp: Date.now()
  });
};

6. Complete Production Setup:
// App.js
function App() {
  return (
    <LazyLoadErrorBoundary componentName="App">
      <Suspense fallback={<LoadingScreen />}>
        <Router>
          <Routes>
            <Route 
              path="/dashboard" 
              element={
                <LazyLoadErrorBoundary componentName="Dashboard">
                  <Suspense fallback={<PageLoader />}>
                    <Dashboard />
                  </Suspense>
                </LazyLoadErrorBoundary>
              } 
            />
          </Routes>
        </Router>
      </Suspense>
    </LazyLoadErrorBoundary>
  );
}

Best Practices:
• Multiple layers of error boundaries
• Automatic retry with exponential backoff
• User-friendly error messages
• Analytics tracking for monitoring
• Version checking mechanism
• Graceful degradation with fallbacks
• Clear cache on version updates
• Network status detection

Result: Robust production app jo failures ko gracefully handle karta hai aur users ko smooth experience deta hai!