Skip to content

[Performance] Unified Lazy Loading Wrapper Across High-Cost Surfaces #583

Description

@Debatreya

Description

Create a reusable Lazy Loading system and apply it across all major heavy surfaces in one pass, owned by one engineer.

Goal:

  • Reduce initial bundle cost
  • Reduce initial render workload
  • Defer expensive UI and media until needed
  • Standardize lazy loading patterns across the app

Can this be fully automatic?

Not fully automatic in a zero-config way.

What is possible:

  • One reusable wrapper/component that handles:
    • Viewport-based mounting
    • Optional dynamic import
    • Skeleton/fallback rendering
    • Optional keepMounted behavior
    • Priority/preload hints

Why not truly automatic:

  • Different components need different triggers (viewport, user click, modal open, tab select, route idle)
  • Data lazy loading (pagination/cursor/server actions) is not the same as UI lazy loading
  • Some content is server-rendered, some client-rendered
  • Image-heavy components need different handling than modal-heavy components

Scope

Implement one shared lazy loading abstraction and apply it to:

  1. Faculty and Staff listing
  2. Tenders listing
  3. Notifications list + modal path
  4. Events list + modal/gallery path
  5. Gallery implementations

Single engineer should complete all of the above in this issue.

Requirements

1. [ ] Build shared lazy loading primitives

Create a shared wrapper system with:

  • LazyLoadBoundary component
  • DynamicLazy helper for dynamic-import components
  • Sensible defaults for intersection observer
  • Fallback slots (skeleton/loading/empty)
  • Optional trigger modes:
    • viewport
    • interaction
    • immediate
  • Optional preload behavior:
    • preloadOnHover
    • preloadOnIdle
  • Keep mounted toggle for modals/tabs to avoid re-fetch churn

2. [ ] Apply wrapper to all target surfaces

  • Faculty and Staff:
    • Wrap list sections and expensive row/media blocks
    • Combine with incremental list rendering strategy
  • Tenders:
    • Wrap heavy table content and archived tab content
    • Defer archived rendering/data until tab active
  • Notifications:
    • Wrap modal rendering path and rich content renderer path
    • Keep list interaction snappy
  • Events:
    • Wrap event modal + gallery/carousel subtree
    • Defer heavy media stack until modal open
  • Gallery:
    • Wrap below-the-fold gallery rows/sections
    • Defer non-visible media work

3. Standardize usage pattern

  • Replace ad-hoc lazy loading with wrapper-based pattern
  • Add concise developer docs for when to use each trigger mode
  • Ensure wrapper can be reused in future list pages

Acceptance Criteria

  • Shared wrapper exists and is used in all 5 target areas
  • Initial page render becomes lighter on target routes
  • Modal and gallery heavy code paths are deferred until needed
  • No UX regression in filters/search/open/close interactions
  • No regression in notifications/events/tenders management flows
  • Wrapper API is documented and easy to apply elsewhere
  • Work completed by one engineer in a single implementation track

Testing Checklist

  • Verify all wrapped sections still render correctly when scrolled into view
  • Verify modal opening still works reliably and content loads correctly
  • Verify tabs (especially tenders archived) load on demand
  • Verify filters/search still function and do not break state
  • Verify mobile performance on long lists and media-heavy pages
  • Compare before/after route performance (initial JS, first interaction, scroll smoothness)

Deliverables

  • Shared lazy loading wrapper utilities
  • Wrapper integration across all listed surfaces
  • Short engineering note:
    • where wrapper was applied
    • trigger mode chosen per area
    • before/after performance summary

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions