perf: route- and modal-level code splitting (React.lazy)
The whole app shipped in one bundle, so the logged-out landing and every page pulled all module code. Split into lazy chunks: - main.tsx: lazy App + the public leaves (WatchPage, Privacy, Terms), so a public /watch share link never downloads the authenticated app. - App.tsx: each module page (Feed, Channels, Playlists, Stats, Scheduler, Config, Users, Settings, Notifications, Messages, Downloads, ChannelPage) and the About/ReleaseNotes/Onboarding modals load on demand behind <Suspense>. - Heavy modals lazy in their parents: PlayerModal (Feed, Playlists), DownloadDialog (DownloadButton — kept out of the feed chunk), and the VideoEditor/ShareDialog/ProfileEditor (DownloadCenter). - Extracted focusAccessRequestsTab + the tab constants to lib/adminUsersTab so callers can pre-select the admin tab without statically importing the now lazy-loaded AdminUsers page (which would defeat the split). Build now emits ~25 chunks. Landing no longer downloads any module code (~350 KB deferred); dev landing Perf 93->95. Verified in a real browser: every page + the video editor load with no console errors.
This commit is contained in:
parent
18a33b96c8
commit
2344902a7f
10 changed files with 167 additions and 117 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { lazy, Suspense, useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { keepPreviousData, useInfiniteQuery, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { ArrowDown, ArrowUp, ArrowLeft, Info, RefreshCw, Trash2, Youtube } from "lucide-react";
|
||||
|
|
@ -7,7 +7,8 @@ import i18n from "../i18n";
|
|||
import { notify, resolveVideo } from "../lib/notifications";
|
||||
import { useDebounced } from "../lib/useDebounced";
|
||||
import VirtualFeed from "./VirtualFeed";
|
||||
import PlayerModal from "./PlayerModal";
|
||||
// Lazy: the in-app YouTube player (IFrame API) loads only when a video is first opened.
|
||||
const PlayerModal = lazy(() => import("./PlayerModal"));
|
||||
|
||||
const PAGE = 60;
|
||||
|
||||
|
|
@ -441,13 +442,15 @@ export default function Feed({
|
|||
)}
|
||||
|
||||
{activeVideo && (
|
||||
<PlayerModal
|
||||
video={activeVideo.video}
|
||||
startAt={activeVideo.startAt}
|
||||
onClose={() => setActiveVideo(null)}
|
||||
onState={onState}
|
||||
onOpenChannel={onOpenChannel}
|
||||
/>
|
||||
<Suspense fallback={null}>
|
||||
<PlayerModal
|
||||
video={activeVideo.video}
|
||||
startAt={activeVideo.startAt}
|
||||
onClose={() => setActiveVideo(null)}
|
||||
onState={onState}
|
||||
onOpenChannel={onOpenChannel}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -647,13 +650,15 @@ export default function Feed({
|
|||
/>
|
||||
)}
|
||||
{activeVideo && (
|
||||
<PlayerModal
|
||||
video={activeVideo.video}
|
||||
startAt={activeVideo.startAt}
|
||||
onClose={() => setActiveVideo(null)}
|
||||
onState={onState}
|
||||
onOpenChannel={onOpenChannel}
|
||||
/>
|
||||
<Suspense fallback={null}>
|
||||
<PlayerModal
|
||||
video={activeVideo.video}
|
||||
startAt={activeVideo.startAt}
|
||||
onClose={() => setActiveVideo(null)}
|
||||
onState={onState}
|
||||
onOpenChannel={onOpenChannel}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
{isFetchingNextPage && (
|
||||
<div className="text-center text-muted py-4">{t("feed.loadingMore")}</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue