From d62822bc0342a681198716fc1a263e0296add29b Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 29 Apr 2026 23:58:07 +0800 Subject: [PATCH] perf: defer noncritical home data --- components/home/lovart-home.tsx | 44 +++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/components/home/lovart-home.tsx b/components/home/lovart-home.tsx index a77d02ffa..48d650b35 100644 --- a/components/home/lovart-home.tsx +++ b/components/home/lovart-home.tsx @@ -479,18 +479,46 @@ export function LovartHome({ const [deletingProjectId, setDeletingProjectId] = useState(null); const [typedPreviewText, setTypedPreviewText] = useState(""); const [previewCursorVisible, setPreviewCursorVisible] = useState(true); + const [isSecondaryDataReady, setIsSecondaryDataReady] = useState(false); const projectSectionRef = useRef(null); const featuredLoadMoreRef = useRef(null); const filesRef = useRef([]); + useEffect(() => { + if (typeof window === "undefined") { + return; + } + + const loadSecondaryData = () => setIsSecondaryDataReady(true); + const idleWindow = window as Window & { + cancelIdleCallback?: (handle: number) => void; + requestIdleCallback?: ( + callback: IdleRequestCallback, + options?: IdleRequestOptions + ) => number; + }; + if (typeof idleWindow.requestIdleCallback === "function") { + const idleId = idleWindow.requestIdleCallback(loadSecondaryData, { + timeout: 1200, + }); + return () => idleWindow.cancelIdleCallback?.(idleId); + } + + const timer = window.setTimeout(loadSecondaryData, 550); + return () => window.clearTimeout(timer); + }, []); + const { data: canvasData, mutate: mutateCanvas } = useSWR<{ success: boolean; data: CanvasProject[]; - }>(isAuthenticated ? "/api/canvas" : null, fetcher); + }>(isAuthenticated && isSecondaryDataReady ? "/api/canvas" : null, fetcher); const { data: featuredPages, size: featuredPageCount, setSize: setFeaturedPageCount, isValidating: isFeaturedValidating } = useSWRInfinite( (pageIndex, previousPageData) => { + if (!isSecondaryDataReady) { + return null; + } if ( previousPageData?.pagination && previousPageData.pagination.page >= previousPageData.pagination.totalPages @@ -508,7 +536,7 @@ export function LovartHome({ ); const { data: membershipData } = useSWR( - isAuthenticated ? "/api/user/membership-summary" : null, + isAuthenticated && isSecondaryDataReady ? "/api/user/membership-summary" : null, fetcher ); @@ -536,10 +564,10 @@ export function LovartHome({ supportsSeed?: boolean; } | null; } | null; - }>(isAuthenticated ? "/api/models" : null, fetcher); + }>(isAuthenticated && isSecondaryDataReady ? "/api/models" : null, fetcher); const { data: navLinksData } = useSWR<{ links: NavLink[] }>( - "/api/nav-links", + isSecondaryDataReady ? "/api/nav-links" : null, fetcher ); @@ -570,19 +598,21 @@ export function LovartHome({ }>("/api/site-settings", fetcher); const { data: tutorialVideosData } = useSWR<{ videos: TutorialVideo[] }>( - siteSettingsData?.tutorialEnabled ? "/api/tutorial-videos" : null, + isSecondaryDataReady && siteSettingsData?.tutorialEnabled + ? "/api/tutorial-videos" + : null, fetcher ); const { data: authSettingsData } = useSWR( - "/api/auth-settings", + isSecondaryDataReady ? "/api/auth-settings" : null, fetcher ); const { data: homeAnimationData } = useSWR<{ enabled?: boolean; htmlContent?: string; fileName?: string; - }>("/api/home-animation", fetcher); + }>(isSecondaryDataReady ? "/api/home-animation" : null, fetcher); const membershipConfig = membershipData?.config; const membershipPlans = membershipConfig?.plans || [];