Skip to content

perf(frontend): blank Suspense → Spin loader, matchMedia resize hook, virtual table scrolling - #6187

Open
PathGao wants to merge 1 commit into
MHSanaei:mainfrom
PathGao:perf/frontend-loading-virtual-scroll
Open

perf(frontend): blank Suspense → Spin loader, matchMedia resize hook, virtual table scrolling#6187
PathGao wants to merge 1 commit into
MHSanaei:mainfrom
PathGao:perf/frontend-loading-virtual-scroll

Conversation

@PathGao

@PathGao PathGao commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

8 files, +42/−20 — all low-cost optimizations in the frontend layer.

Visual: blank Suspense fallback → centered <Spin>

routes.tsx + LazyMount.tsx — every route change and lazy modal used to render nothing (fallback={null}) while the code chunk loaded, showing a blank screen. Now shows a centered antd Spin loader, matching the established loading pattern already used in the codebase.

Efficient: useMediaQuery switched from resize to matchMedia

useMediaQuery.ts — the hook listened to window.resize which fires on every pixel of window drag, triggering state updates and React re-renders in every component tree that calls it (most pages). Now uses the native window.matchMedia("(max-width: Npx)").change event which fires only when the query actually flips. Also exports MOBILE_BREAKPOINT_PX.

SubPage.tsx — dropped a duplicate inline isMobile implementation (its own useState + resize listener at a hardcoded 576px breakpoint) in favor of the shared useMediaQuery(576) hook. Net −6 lines.

Efficient: virtual scrolling on 4 large tables

ClientsPage.tsx, InboundList.tsx, HostList.tsx, NodeList.tsx — added antd Table virtual prop with scroll.y (viewport-relative calc). On large datasets, only the visible rows are rendered in the DOM. Tables with pagination={false} (HostList, NodeList) benefit most; paginated tables benefit at larger page sizes.

Table scroll.y
ClientsPage calc(100vh - 380px)
InboundList calc(100vh - 320px)
HostList calc(100vh - 280px)
NodeList calc(100vh - 320px)

Verification

  • All changes are TypeScript-level only (no backend changes)
  • Suspense/Spin/virtual are already used elsewhere in this codebase
  • No new dependencies introduced

… matchMedia hook, add virtual table scrolling

- routes.tsx, LazyMount.tsx: replace Suspense fallback={null} with Spin
  loader so page transitions and lazy modals never show blank content
- useMediaQuery.ts: switch from resize event to matchMedia change event,
  eliminating state updates on every pixel drag; export MOBILE_BREAKPOINT_PX
- SubPage.tsx: drop duplicate inline isMobile logic (7 lines), use shared
  useMediaQuery(576) (2 lines)
- ClientsPage, InboundList, HostList, NodeList: add virtual + scroll.y to
  Table for viewport-only DOM rendering of large datasets
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant