vkashti / components / LazyComponents.tsx
LazyComponents.tsx
Raw
'use client';

import dynamic from 'next/dynamic';
import { Suspense } from 'react';
import { ReactNode } from 'react';

type FAQProps = { 
  questions: { question: string; answer: ReactNode }[] 
};

type ReviewsProps = {
  reviews: any[]
};

// Dynamically import heavy components to reduce initial JS bundle size
export const LazyMap = dynamic(() => import('@/components/ui/Map'), {
  loading: () => <div className="h-[400px] w-full bg-slate-100 animate-pulse rounded-lg"></div>,
  ssr: false, // Don't server-render this component to reduce initial HTML size
});

export const LazyFAQ = dynamic<FAQProps>(() => 
  import('@/components/ui/FAQ').then(mod => mod.default), {
  // Delay loading until needed
  loading: () => <div className="py-4 space-y-2" aria-label="Loading FAQs">
    {[1, 2, 3].map(i => (
      <div key={i} className="h-20 bg-slate-100 animate-pulse rounded-lg mb-2"></div>
    ))}
  </div>,
});

export const LazyReviews = dynamic<ReviewsProps>(() => 
  import('@/components/ui/Reviews').then(mod => mod.default), {
  loading: () => <div className="py-4 space-y-2" aria-label="Loading reviews">
    {[1, 2, 3].map(i => (
      <div key={i} className="h-32 bg-slate-100 animate-pulse rounded-lg mb-2"></div>
    ))}
  </div>,
  ssr: false,
});

export const LazyEvents = dynamic(() => import('@/app/events/page'), {
  loading: () => <div className="py-4" aria-label="Loading events">
    <div className="h-64 bg-slate-100 animate-pulse rounded-lg"></div>
  </div>,
  ssr: false,
});

export const LazyDeals = dynamic(() => import('@/app/deals/page'), {
  loading: () => <div className="py-4" aria-label="Loading deals">
    <div className="h-64 bg-slate-100 animate-pulse rounded-lg"></div>
  </div>,
  ssr: false,
});

// Optimized component loader with Intersection Observer
export function LazyLoad({ children }: { children: React.ReactNode }) {
  return (
    <Suspense fallback={<div className="h-20 bg-slate-100 animate-pulse rounded-lg" aria-label="Loading content"></div>}>
      {children}
    </Suspense>
  );
}