From 34fdae1e97828f59d7573a63a667f9cece452b5a Mon Sep 17 00:00:00 2001 From: plebeius Date: Mon, 23 Feb 2026 18:51:36 +0800 Subject: [PATCH] perf(app): enable FeedCacheContainer always, lazy-load modals FeedCacheContainer now always renders since Virtuoso is used for all feed modes (infinite scroll and pagination). Feed routes are always rendered by FeedCacheContainer; route elements are null. Outlet only renders for thread, pending, and modqueue routes. Removed clearFeeds effect. Modals lazy-loaded with Suspense fallback=null for bundle splitting. --- src/app.tsx | 69 +++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index 9002eaf7..5597c603 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { lazy, Suspense, useEffect } from 'react'; import { Navigate, Outlet, Route, Routes, useLocation, useParams } from 'react-router-dom'; import { useAccount, useAccountComment, useSubplebbit } from '@plebbit/plebbit-react-hooks'; import useAccountsStore from '@plebbit/plebbit-react-hooks/dist/stores/accounts'; @@ -8,38 +8,37 @@ import { preloadThemeAssets } from './lib/utils/preload-utils'; import useReplyModalStore from './stores/use-reply-modal-store'; import useCreateBoardModalStore from './stores/use-create-board-modal-store'; import useSpecialThemeStore from './stores/use-special-theme-store'; -import useFeedViewSettingsStore from './stores/use-feed-view-settings-store'; -import useFeedCacheStore from './stores/use-feed-cache-store'; import useIsMobile from './hooks/use-is-mobile'; import useTheme from './hooks/use-theme'; import { useDirectories } from './hooks/use-directories'; import { useResolvedSubplebbitAddress } from './hooks/use-resolved-subplebbit-address'; import { getSubplebbitAddress, isPostRoute, isPendingPostRoute, isModQueueRoute } from './lib/utils/route-utils'; import styles from './app.module.css'; +import { DesktopBoardButtons, MobileBoardButtons } from './components/board-buttons'; +import Board from './views/board'; import Blotter from './views/blotter'; +import Catalog from './views/catalog'; import FAQ from './views/faq'; import Home from './views/home'; -import Rules from './views/rules'; -import NotFound from './views/not-found'; +import ModQueueView from './views/mod-queue'; import NotAllowed from './views/not-allowed'; +import NotFound from './views/not-found'; import PendingPost from './views/pending-post'; import Post from './views/post'; -import Board from './views/board'; -import Catalog from './views/catalog'; -import ModQueueView from './views/mod-queue'; -import { DesktopBoardButtons, MobileBoardButtons } from './components/board-buttons'; +import Rules from './views/rules'; import BoardHeader from './components/board-header'; import ChallengeModal from './components/challenge-modal'; -import CreateBoardModal from './components/create-board-modal'; import FeedCacheContainer from './components/feed-cache-container'; import ReplyModal from './components/reply-modal'; import PostForm from './components/post-form'; import BoardBlotter from './components/board-blotter'; import BoardsBar from './components/boardsbar'; -import BoardsBarEditModal from './components/boardsbar-edit-modal'; -import DirectoryModal from './components/directory-modal'; -import DisclaimerModal from './components/disclaimer-modal'; -import SettingsModal from './components/settings-modal'; + +const BoardsBarEditModal = lazy(() => import('./components/boardsbar-edit-modal')); +const CreateBoardModal = lazy(() => import('./components/create-board-modal')); +const DirectoryModal = lazy(() => import('./components/directory-modal')); +const DisclaimerModal = lazy(() => import('./components/disclaimer-modal')); +const SettingsModal = lazy(() => import('./components/settings-modal')); // Preload all theme assets (buttons, backgrounds) immediately on app load // to prevent visible loading delays when switching themes @@ -58,20 +57,10 @@ const BoardLayout = () => { const subplebbitAddress = boardIdentifier ? getSubplebbitAddress(boardIdentifier, directories) : undefined; const pendingPost = useAccountComment({ commentIndex: accountCommentIndex ? parseInt(accountCommentIndex) : undefined }); const { closeCreateBoardModal } = useCreateBoardModalStore(); - const enableInfiniteScroll = useFeedViewSettingsStore((state) => state.enableInfiniteScroll); - const clearFeeds = useFeedCacheStore((state) => state.clearFeeds); - const isOnPostRoute = isPostRoute(location.pathname); const isOnPendingPostRoute = isPendingPostRoute(location.pathname); const isOnModQueueRoute = isModQueueRoute(location.pathname); - const shouldRenderOutlet = !enableInfiniteScroll || isOnPostRoute || isOnPendingPostRoute || isOnModQueueRoute; - - // Clear feed cache when switching from infinite scroll to pagination - useEffect(() => { - if (!enableInfiniteScroll) { - clearFeeds(); - } - }, [enableInfiniteScroll, clearFeeds]); + const shouldRenderOutlet = isOnPostRoute || isOnPendingPostRoute || isOnModQueueRoute; // Christmas theme const { isEnabled: isSpecialEnabled } = useSpecialThemeStore(); @@ -97,10 +86,18 @@ const BoardLayout = () => { return (
- - - - + + + + + + + + + + + + {isMobile ? (subplebbitAddress || isInAllView || isInModView || isInSubscriptionsView || pendingPost?.subplebbitAddress || isOnModQueueRoute) && ( @@ -116,7 +113,7 @@ const BoardLayout = () => { )} - {enableInfiniteScroll && } + {shouldRenderOutlet && }
); @@ -154,7 +151,11 @@ const GlobalLayout = () => { subplebbitAddress={subplebbitAddress} /> )} - {isInSettingsView && } + {isInSettingsView && ( + + + + )} ); @@ -232,9 +233,9 @@ const ModQueueRoute = () => { }; const App = () => { - const enableInfiniteScroll = useFeedViewSettingsStore((state) => state.enableInfiniteScroll); - const boardFeedElement = enableInfiniteScroll ? null : ; - const catalogFeedElement = enableInfiniteScroll ? null : ; + // Feed routes are always rendered by FeedCacheContainer (Virtuoso used for all modes) + const boardFeedElement = null; + const catalogFeedElement = null; return (