Lazy loads dashboard modules using IntersectionObserver. Defers dynamic import() calls until the dashboard container enters the viewport, reducing initial page load and improving Time to Interactive (TTI).
Falls back to immediate loading when IntersectionObserver is unavailable.
Performance
Each lazy dashboard defers its dynamic import() until the section scrolls into view (plus a DEFAULT_ROOT_MARGIN pre-fetch margin), preventing Chart.js (~200 KB), D3 (~250 KB) and PapaParse (~50 KB) from blocking the initial parse/render.
The default pre-fetch margin (2000 px) is intentionally generous so that on dedicated /dashboards/<name>.html pages โ where a single dashboard container frequently sits 1 000โ1 500 px below the fold beneath hero + navigation โ the IntersectionObserver still fires immediately without any user scroll. A narrower 200 px margin (the previous default) silently broke those pages because the dashboard never entered the observer's root.
Description
Lazy loads dashboard modules using IntersectionObserver. Defers dynamic import() calls until the dashboard container enters the viewport, reducing initial page load and improving Time to Interactive (TTI).
Falls back to immediate loading when IntersectionObserver is unavailable.
Performance
Each lazy dashboard defers its dynamic import() until the section scrolls into view (plus a
DEFAULT_ROOT_MARGINpre-fetch margin), preventing Chart.js (~200 KB), D3 (~250 KB) and PapaParse (~50 KB) from blocking the initial parse/render.The default pre-fetch margin (
2000 px) is intentionally generous so that on dedicated/dashboards/<name>.htmlpages โ where a single dashboard container frequently sits 1 000โ1 500 px below the fold beneath hero + navigation โ the IntersectionObserver still fires immediately without any user scroll. A narrower 200 px margin (the previous default) silently broke those pages because the dashboard never entered the observer's root.