Skip to content

Commit 652cd36

Browse files
authored
perf: Lazy-load heavy route pages to reduce initial bundle (#1661)
Converts economy, market data, forecasting, and reference data pages to React.lazy + Suspense, matching the existing cookbook pattern. Co-authored-by: Ben Coombs <bjcoombs@users.noreply.github.com>
1 parent 2a4a135 commit 652cd36

1 file changed

Lines changed: 60 additions & 17 deletions

File tree

frontend/src/App.tsx

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,12 @@ import { ReconciliationPage, ReconciliationDetailPage } from '@/features/reconci
2929
import { AuditLogPage } from '@/features/audit'
3030
import { StarlarkConfigPage, StarlarkDetailPage } from '@/features/sagas'
3131
import { MappingsPage, MappingDetailPage } from '@/features/mappings'
32-
import { ReferenceDataHubPage, InstrumentsPage, AccountTypesPage, NodesPage, ValuationRulesPage } from '@/features/reference-data'
3332
import { InternalAccountsPage, InternalAccountDetailPage } from '@/features/internal-accounts'
34-
import { MarketDataPage, DatasetDetailPage } from '@/features/market-data'
35-
import { ForecastingPage } from '@/features/forecasting'
3633
import { DashboardPage } from '@/features/dashboard'
3734
import { McpConfigPage } from '@/features/mcp-config'
3835
import { TransactionsPage } from '@/features/transactions'
3936
import { UsersListPage, UserDetailPage } from '@/features/identity'
4037
import { CookbookPage } from '@/features/cookbook'
41-
import { EconomyOverviewPage, EconomyCreatePage, EconomyEditPage, EconomyExplorePage, EconomyDraftPage } from '@/features/economy'
4238

4339
const CookbookPatternsPage = lazy(() =>
4440
import('@/features/cookbook/pages/patterns').then((m) => ({ default: m.CookbookPatternsPage })),
@@ -52,6 +48,53 @@ const CookbookDetailPage = lazy(() =>
5248
const CookbookGraphPage = lazy(() =>
5349
import('@/features/cookbook/pages/graph').then((m) => ({ default: m.CookbookGraphPage })),
5450
)
51+
52+
// Economy pages (lazy-loaded: graph rendering with ELK/Cytoscape)
53+
const EconomyOverviewPage = lazy(() =>
54+
import('@/features/economy/pages/economy-overview-page').then((m) => ({ default: m.EconomyOverviewPage })),
55+
)
56+
const EconomyCreatePage = lazy(() =>
57+
import('@/features/economy/pages/economy-create-page').then((m) => ({ default: m.EconomyCreatePage })),
58+
)
59+
const EconomyEditPage = lazy(() =>
60+
import('@/features/economy/pages/economy-edit-page').then((m) => ({ default: m.EconomyEditPage })),
61+
)
62+
const EconomyExplorePage = lazy(() =>
63+
import('@/features/economy/pages/economy-explore-page').then((m) => ({ default: m.EconomyExplorePage })),
64+
)
65+
const EconomyDraftPage = lazy(() =>
66+
import('@/features/economy/pages/economy-draft-page').then((m) => ({ default: m.EconomyDraftPage })),
67+
)
68+
69+
// Market data pages (lazy-loaded: chart rendering)
70+
const MarketDataPage = lazy(() =>
71+
import('@/features/market-data/pages/index').then((m) => ({ default: m.MarketDataPage })),
72+
)
73+
const DatasetDetailPage = lazy(() =>
74+
import('@/features/market-data/pages/[datasetCode]').then((m) => ({ default: m.DatasetDetailPage })),
75+
)
76+
77+
// Forecasting page (lazy-loaded: data visualization)
78+
const ForecastingPage = lazy(() =>
79+
import('@/features/forecasting/pages/index').then((m) => ({ default: m.ForecastingPage })),
80+
)
81+
82+
// Reference data pages (lazy-loaded: large component trees)
83+
const ReferenceDataHubPage = lazy(() =>
84+
import('@/features/reference-data/pages/index').then((m) => ({ default: m.ReferenceDataHubPage })),
85+
)
86+
const InstrumentsPage = lazy(() =>
87+
import('@/features/reference-data/pages/instruments/index').then((m) => ({ default: m.InstrumentsPage })),
88+
)
89+
const AccountTypesPage = lazy(() =>
90+
import('@/features/reference-data/pages/account-types/index').then((m) => ({ default: m.AccountTypesPage })),
91+
)
92+
const NodesPage = lazy(() =>
93+
import('@/features/reference-data/pages/nodes/index').then((m) => ({ default: m.NodesPage })),
94+
)
95+
const ValuationRulesPage = lazy(() =>
96+
import('@/features/reference-data/pages/valuation-rules/index').then((m) => ({ default: m.ValuationRulesPage })),
97+
)
5598
import { ThemePreviewPanel } from '@/components/dev/theme-preview-panel'
5699

57100
// Placeholder page components - replaced as each page task is implemented
@@ -302,21 +345,21 @@ function AppShellLayout() {
302345
element={<FeatureGuard feature="sagas">{guarded(<StarlarkConfigPage isPlatformAdmin={isPlatformAdmin} />)}</FeatureGuard>}
303346
/>
304347
<Route path="/starlark-config/:definitionId" element={<FeatureGuard feature="sagas">{guarded(<StarlarkDetailPage />)}</FeatureGuard>} />
305-
<Route path="/market-data" element={<FeatureGuard feature="market-data">{guarded(<MarketDataPage />)}</FeatureGuard>} />
306-
<Route path="/market-data/:datasetCode" element={<FeatureGuard feature="market-data">{guarded(<DatasetDetailPage />)}</FeatureGuard>} />
307-
<Route path="/forecasting" element={<FeatureGuard feature="forecasting">{guarded(<ForecastingPage />)}</FeatureGuard>} />
308-
<Route path="/reference-data" element={<FeatureGuard feature="reference-data">{guarded(<ReferenceDataHubPage />)}</FeatureGuard>} />
309-
<Route path="/reference-data/instruments" element={<FeatureGuard feature="reference-data">{guarded(<InstrumentsPage />)}</FeatureGuard>} />
310-
<Route path="/reference-data/account-types" element={<FeatureGuard feature="reference-data">{guarded(<AccountTypesPage />)}</FeatureGuard>} />
311-
<Route path="/reference-data/nodes" element={<FeatureGuard feature="reference-data">{guarded(<NodesPage />)}</FeatureGuard>} />
312-
<Route path="/reference-data/valuation-rules" element={<FeatureGuard feature="reference-data">{guarded(<ValuationRulesPage />)}</FeatureGuard>} />
348+
<Route path="/market-data" element={<FeatureGuard feature="market-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<MarketDataPage />)}</Suspense></FeatureGuard>} />
349+
<Route path="/market-data/:datasetCode" element={<FeatureGuard feature="market-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<DatasetDetailPage />)}</Suspense></FeatureGuard>} />
350+
<Route path="/forecasting" element={<FeatureGuard feature="forecasting"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<ForecastingPage />)}</Suspense></FeatureGuard>} />
351+
<Route path="/reference-data" element={<FeatureGuard feature="reference-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<ReferenceDataHubPage />)}</Suspense></FeatureGuard>} />
352+
<Route path="/reference-data/instruments" element={<FeatureGuard feature="reference-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<InstrumentsPage />)}</Suspense></FeatureGuard>} />
353+
<Route path="/reference-data/account-types" element={<FeatureGuard feature="reference-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<AccountTypesPage />)}</Suspense></FeatureGuard>} />
354+
<Route path="/reference-data/nodes" element={<FeatureGuard feature="reference-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<NodesPage />)}</Suspense></FeatureGuard>} />
355+
<Route path="/reference-data/valuation-rules" element={<FeatureGuard feature="reference-data"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<ValuationRulesPage />)}</Suspense></FeatureGuard>} />
313356
<Route path="/gateway-mappings" element={<FeatureGuard feature="mappings">{guarded(<MappingsPage />)}</FeatureGuard>} />
314357
<Route path="/gateway-mappings/:mappingId" element={<FeatureGuard feature="mappings">{guarded(<MappingDetailPage />)}</FeatureGuard>} />
315-
<Route path="/economy" element={<FeatureGuard feature="economy">{guarded(<EconomyOverviewPage />)}</FeatureGuard>} />
316-
<Route path="/economy/create" element={<FeatureGuard feature="economy">{guarded(<EconomyCreatePage />)}</FeatureGuard>} />
317-
<Route path="/economy/edit" element={<FeatureGuard feature="economy">{guarded(<EconomyEditPage />)}</FeatureGuard>} />
318-
<Route path="/economy/explore" element={<FeatureGuard feature="economy">{guarded(<EconomyExplorePage />)}</FeatureGuard>} />
319-
<Route path="/economy/draft" element={<FeatureGuard feature="economy">{guarded(<EconomyDraftPage />)}</FeatureGuard>} />
358+
<Route path="/economy" element={<FeatureGuard feature="economy"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<EconomyOverviewPage />)}</Suspense></FeatureGuard>} />
359+
<Route path="/economy/create" element={<FeatureGuard feature="economy"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<EconomyCreatePage />)}</Suspense></FeatureGuard>} />
360+
<Route path="/economy/edit" element={<FeatureGuard feature="economy"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<EconomyEditPage />)}</Suspense></FeatureGuard>} />
361+
<Route path="/economy/explore" element={<FeatureGuard feature="economy"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<EconomyExplorePage />)}</Suspense></FeatureGuard>} />
362+
<Route path="/economy/draft" element={<FeatureGuard feature="economy"><Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}>{guarded(<EconomyDraftPage />)}</Suspense></FeatureGuard>} />
320363
<Route path="/mcp-config" element={<FeatureGuard feature="mcp-config">{guarded(<McpConfigPage />)}</FeatureGuard>} />
321364
<Route path="/cookbook" element={guarded(<CookbookPage />)} />
322365
<Route path="/cookbook/patterns" element={guarded(<Suspense fallback={<div className="h-96 animate-pulse rounded bg-muted" />}><CookbookPatternsPage /></Suspense>)} />

0 commit comments

Comments
 (0)