Improve page loading performance by deferring off-screen content

Implement lazy loading for lower sections of the homepage to optimize initial render and improve user experience.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1f7e7e89-a520-4970-9645-37daadc466dc
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 97dab47f-9107-41f0-9b7a-5900b3b486e6
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/1f7e7e89-a520-4970-9645-37daadc466dc/ZApZ5Qi
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic 2026-03-05 14:36:42 +00:00
parent 970c395184
commit 9a81e63740

View File

@ -15,7 +15,7 @@ import { RecipeWidget } from "@/components/recipe-widget";
import { NewsWidget } from "@/components/news-widget";
import { SidebarWeatherWidget } from "@/components/weather-widget";
import { BreakingNewsWidget } from "@/components/breaking-news-widget";
import { useState, useEffect, useCallback, useRef, useMemo } from "react";
import { useState, useEffect, useCallback, useRef, useMemo, lazy, Suspense } from "react";
function useFocalPoints() {
const { data } = useQuery<Record<string, { x: number; y: number }>>({
@ -466,6 +466,33 @@ function FeaturedCarousel({ articles, popular, galleryImages, focalPoints }: { a
);
}
function LazySection({ children, minHeight = "200px" }: { children: JSX.Element; minHeight?: string }) {
const ref = useRef<HTMLDivElement>(null);
const [visible, setVisible] = useState(false);
useEffect(() => {
const el = ref.current;
if (!el) return;
const obs = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setVisible(true);
obs.disconnect();
}
},
{ rootMargin: "300px" }
);
obs.observe(el);
return () => obs.disconnect();
}, []);
return (
<div ref={ref} style={{ minHeight: visible ? undefined : minHeight }}>
{visible ? children : null}
</div>
);
}
function BentoSkeleton() {
return (
<div className="space-y-4">
@ -663,41 +690,47 @@ export default function Home() {
</div>
{gridRows.map((row, ri) => (
<div key={`row-group-${ri}`}>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{row.map((item) =>
item.type === "widget"
? <div key={item.key}>{item.widget!.el}</div>
: item.type === "ad"
? <div key={item.key} className="h-full" data-testid={`ad-grid-${item.key}`}><ArticleCardAd /></div>
: item.article
? <MediumCard key={item.key} article={item.article} focalPoints={focalPoints} />
: null
)}
{ri === gridRows.length - 1 && widePickedArticles.length > 0 && (
<div className="sm:col-span-2 lg:col-span-4 grid grid-cols-1 sm:grid-cols-2 gap-4">
<WideCardClassic article={widePickedArticles[0]} focalPoints={focalPoints} />
{widePickedArticles[1] && <WideCardClassic article={widePickedArticles[1]} focalPoints={focalPoints} />}
</div>
)}
<LazySection key={`row-group-${ri}`} minHeight="280px">
<div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{row.map((item) =>
item.type === "widget"
? <div key={item.key}>{item.widget!.el}</div>
: item.type === "ad"
? <div key={item.key} className="h-full" data-testid={`ad-grid-${item.key}`}><ArticleCardAd /></div>
: item.article
? <MediumCard key={item.key} article={item.article} focalPoints={focalPoints} />
: null
)}
{ri === gridRows.length - 1 && widePickedArticles.length > 0 && (
<div className="sm:col-span-2 lg:col-span-4 grid grid-cols-1 sm:grid-cols-2 gap-4">
<WideCardClassic article={widePickedArticles[0]} focalPoints={focalPoints} />
{widePickedArticles[1] && <WideCardClassic article={widePickedArticles[1]} focalPoints={focalPoints} />}
</div>
)}
</div>
</div>
</div>
</LazySection>
))}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{bottomSection.map((item, i) => (
<div key={`bottom-${i}`}>
{item.el}
</div>
))}
</div>
<LazySection minHeight="280px">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{bottomSection.map((item, i) => (
<div key={`bottom-${i}`}>
{item.el}
</div>
))}
</div>
</LazySection>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<PhotoGalleryWidget key="extra-gallery" />
<NewsWidget key="extra-news" />
<RecipeWidget key="extra-recipe" />
<div className="h-full"><ArticleCardAd /></div>
</div>
<LazySection minHeight="280px">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<PhotoGalleryWidget key="extra-gallery" />
<NewsWidget key="extra-news" />
<RecipeWidget key="extra-recipe" />
<div className="h-full"><ArticleCardAd /></div>
</div>
</LazySection>
</main>
<Footer />