Faster Dashboards with Bundle Splitting
Faster Dashboards with Bundle Splitting
Release: v0.1.41 · Performance · PERF-01
Background
The sanctions screening dashboard is a multi-page application. Before this release, every page's JavaScript — billing, sanctions, matches, and settings — was included in the initial bundle delivered to the browser on first load. This meant users paid the full parse and execution cost of all dashboard code before any single page became interactive.
On fast connections this was largely invisible. On slower mobile or corporate-proxied connections, the cumulative cost of ~93 KB of JavaScript across four pages created a noticeable delay before the UI responded.
What We Changed
Dynamic imports on heavy pages
The three heaviest pages now use next/dynamic to split their components into separate chunks:
import dynamic from 'next/dynamic'
import { PageSkeleton } from '@/components/ui/page-skeleton'
const BillingContent = dynamic(
() => import('./billing-content'),
{ loading: () => <PageSkeleton /> }
)
export default function BillingPage() {
return <BillingContent />
}
The same pattern is applied to the sanctions and settings pages. The matches page, at 18 KB, is a candidate for a future pass.
What this means in practice:
- The browser only downloads a page's JavaScript when the user navigates to it.
- While the chunk loads, a
<PageSkeleton />placeholder is shown immediately, so the layout is visible with no blank-screen flash. - Subsequent visits to the same page use the cached chunk.
Removed unused dependency
@tanstack/react-query was present in package.json but not used anywhere in the application. It has been removed. This eliminates its contribution to the bundle without any functional change.
Note for contributors: If React Query is needed in the future for client-side data fetching, re-add it at that point and wire it up with a
QueryClientProviderat the appropriate layout level.
Pages Affected
| Page | Approx. size | Dynamic import added |
|---|---|---|
| Billing | 31 KB | ✅ Yes |
| Sanctions | 25 KB | ✅ Yes |
| Settings | 19 KB | ✅ Yes |
| Matches | 18 KB | 🔜 Planned |
For Developers
When adding new dashboard pages, apply the same pattern if the page component is likely to exceed ~15 KB:
- Split the page's main content into a
*-content.tsxfile. - In
page.tsx, import it vianext/dynamicwith a<PageSkeleton />fallback. - Avoid importing large third-party libraries at the top level of
page.tsx.