- React Version: 19.2.0 with React Compiler enabled
- Build Tool: Vite 7 + Rollup (TanStack Start SSR)
- State Management: Zustand, TanStack Query
- Real-time: WebSocket for trading data
- UI: Radix UI, TanStack Virtual/Table
- Install
web-vitalslibrary for LCP, INP, CLS tracking - Create performance monitoring utility (
src/lib/performance/web-vitals.ts) - Set up reporting to console/analytics in dev mode
Targets (2026 Standards):
- LCP (Largest Contentful Paint): < 2.5s
- INP (Interaction to Next Paint): < 200ms
- CLS (Cumulative Layout Shift): < 0.1
- Install
vite-bundle-analyzerfor treemap visualization - Install
rollup-plugin-visualizerfor circular diagrams - Consider
sondafor sourcemap-based accurate post-minification analysis - Add npm scripts for analysis (
pnpm build:analyze,pnpm perf:bundle)
- Document how to use new Chrome DevTools React Performance Tracks
- Scheduler track analysis (Blocking, Transition, Suspense, Idle)
- Component render duration visualization
- Enable "Record why each component rendered" in settings
- Document profiling workflow for the team
- Set up profiling builds (
react-dom/profiling)
- Profile initial page load with React DevTools
- Identify components with excessive re-renders
- Check React Compiler effectiveness (auto-memoization)
- Identify architectural issues compiler can't fix
- Take baseline heap snapshot
- Perform typical user flows (navigate, trade, etc.)
- Compare heap snapshots for growth
- Search for "Detached DOM nodes"
- Audit useEffect cleanup functions
- Check WebSocket subscription cleanup
- Check TanStack Query subscription cleanup
- Analyze WebSocket message frequency
- Check for unnecessary full payload updates (vs delta)
- Profile API request waterfall
- Check for request deduplication (TanStack Query)
- Generate production build with source maps
- Run bundle analyzer
- Identify large dependencies
- Check tree-shaking effectiveness
- Identify code splitting opportunities
- Store baseline metrics (
perf-baseline.json) - Create comparison script (
pnpm perf:compare)
- Audit
useTransitionusage for heavy state updates - Implement
startTransitionfor non-urgent updates - Use
useDeferredValuefor expensive derived state - Check proper Lane prioritization in Performance Tracks
Use cases to check:
- Tab switching
- Large table/list rendering
- Chart updates
- Search/filter operations
- Verify compiler is working (check build output)
- Identify patterns compiler can't optimize
- Remove manual memo/useCallback where compiler handles it
- Keep manual optimization for edge cases
- Audit Suspense boundary placement
- Check for over-nested boundaries
- Implement granular loading states
- Implement message batching (buffer in ref, flush on interval)
- Audit re-render frequency on WebSocket messages
- Consider delta updates for orderbook/trades
- Implement backpressure control if needed
- Check TanStack Virtual usage for large lists
- Ensure orderbook uses virtualization
- Ensure trade history uses virtualization
- Check positions/orders tables
- Identify CPU-intensive calculations
- Consider Web Workers for:
- Large data aggregation
- Chart calculations
- Price formatting at scale
- Audit all useEffect hooks for proper cleanup
- Check WebSocket listeners removal
- Check event listener cleanup
- Check interval/timeout cleanup
- Verify TanStack Query unsubscribe on unmount
- Check for closures holding stale references
- Audit large object retention
- Check for detached DOM node patterns
- Analyze current chunk strategy
- Implement route-based splitting (TanStack Router
autoCodeSplitting: true) - Lazy load heavy components using
lazyRouteComponent:- TradingViewChart, MobileTerminal, GlobalModals
- DepositModal, GlobalSettingsDialog
- All position tabs (Balances, Funding, History, Orders, Positions, Twap)
- Check vendor chunk optimization (radix, tanstack, web3)
- Created
src/lib/lazy.tsutility for consistent lazy loading - Created
docs/tanstack-start-optimization.mddocumentation
- Verify ESM imports throughout
- Check sideEffects in package.json
- Audit barrel imports (avoid re-exporting everything)
- Check icon library tree-shaking
- Check image optimization
- Verify font loading strategy
- Check CSS delivery (Tailwind purging)
# Generate bundle visualization (opens treemap in browser)
pnpm build:analyze
# Alternative: quick bundle visualizer
pnpm perf:bundle
# Compare current build to baseline (run after pnpm build)
pnpm perf:compareIn development mode, access performance tools via window.perf:
// Core Web Vitals summary
window.perf.vitals()
// Component render analysis
window.perf.renders()
// Memory trend analysis
window.perf.memory()
// Network & resource analysis
window.perf.network()
// Take memory snapshot
window.perf.snapshot()// For production profiling
import { createRoot } from 'react-dom/profiling'- Open DevTools → Memory tab
- Take Heap Snapshot (baseline)
- Perform user actions
- Take another snapshot
- Compare snapshots
- Filter by "Detached" to find leaks
- Open DevTools → Performance tab
- Record interaction
- Look for "React" tracks:
- Scheduler (Blocking, Transition, Suspense, Idle)
- Components render duration
- Researched React 19.2 performance measurement techniques
- Documented React Performance Tracks (new in 19.2)
- Documented Core Web Vitals targets
- Created measurement infrastructure plan
- Installed web-vitals library
- Set up bundle analyzers (vite-bundle-analyzer, rollup-plugin-visualizer)
- Created performance monitoring utilities:
src/lib/performance/web-vitals.ts- Core Web Vitals tracking (LCP, INP, CLS, FCP, TTFB)src/lib/performance/memory.ts- Heap memory monitoring & leak detectionsrc/lib/performance/render-tracker.ts- Component render profilingsrc/lib/performance/network.ts- Network & WebSocket metricssrc/lib/performance/profiler.tsx- React Profiler wrapper componentsrc/lib/performance/init.ts- Auto-initialization for dev mode
- Integrated performance monitoring into RootProvider
- Added
window.perfdev tools API for console access - Configured Vite with manual chunks for better code splitting
- Created initial profiling baseline (
perf-baseline.json) - Ran bundle analysis and identified optimization targets
- Created
pnpm perf:comparescript for tracking improvements
- Researched TanStack Start/Router code splitting best practices
- Enabled
autoCodeSplitting: truein TanStack Start vite plugin - Created
src/lib/lazy.tsutility usinglazyRouteComponent - Implemented component-level code splitting:
MobileTerminal(46.7KB split from main)GlobalModalsincluding DepositModal & GlobalSettingsDialogTradingViewChart(14.6KB split)- All 6 position tabs (Balances, Funding, History, Orders, Positions, Twap)
- Created
docs/tanstack-start-optimization.mddocumentation - Results: Index route reduced from 380KB to 229KB (-40%)
- Created
docs/websocket-optimization.md:- Message batching with requestAnimationFrame
- Backpressure control patterns
- Web Worker offloading strategies
- Delta updates vs full snapshots
- Created
docs/memory-management.md:- Chrome DevTools heap snapshot workflow
- Common React memory leak patterns
- useEffect cleanup checklist
- TanStack Query cache cleanup
- Created
docs/concurrent-rendering.md:- useTransition for non-urgent updates
- useDeferredValue for expensive renders
- React 19.2 Performance Tracks
- Suspense boundary optimization
- Created
docs/web3-bundle-optimization.md:- wagmi/viem lazy loading challenges
- Connector lazy loading strategies
- Tree-shaking verification
- Researched message batching strategies (buffer + rAF flush)
- Researched backpressure handling for high-frequency updates
- Researched delta updates vs full payload patterns
- Researched Web Worker offloading for message processing
- Created
docs/websocket-optimization.md
Key findings:
- Current architecture uses Zustand store with reference counting (good)
- Ring buffer already implemented for trades (good)
- Opportunities: rAF batching, ref-based updates, Web Workers
- Documented Chrome DevTools heap snapshot workflow
- Documented common React memory leak patterns
- Audited useEffect cleanup patterns in codebase
- Documented TanStack Query cleanup strategies
- Documented WebSocket listener cleanup patterns
- Created
docs/memory-management.md
Key findings:
- Most cleanup patterns are implemented correctly
- useSub hook has proper cleanup
- Ring buffer uses useSyncExternalStore correctly
- Researched useTransition for tab switching, filters
- Researched useDeferredValue for expensive derived state
- Researched Suspense boundary optimization
- Documented React Performance Tracks usage
- Created
docs/concurrent-rendering.md
Key findings:
- No useTransition/useDeferredValue currently used
- Opportunities: positions panel tabs, token selector, orderbook
- Researched dynamic import patterns for wagmi
- Identified wallet-dependent code paths (31 files)
- Documented lazy connector loading approach
- Created
docs/web3-bundle-optimization.md
Key findings:
- Full lazy load difficult due to provider requirement
- WalletConnect connector (~50KB) can be lazy loaded
- Tree-shaking already in use
| Metric | Target | Current | Status |
|---|---|---|---|
| LCP | < 2.5s | TBD (run app) | 🔴 |
| INP | < 200ms | TBD (run app) | 🔴 |
| CLS | < 0.1 | TBD (run app) | 🔴 |
| Bundle Size (JS) | < 500KB main | 568KB | 🟡 |
| Memory (idle) | TBD | TBD | 🔴 |
| Memory (after 10min) | TBD | TBD | 🔴 |
| Chunk | Size | Gzip | Notes |
|---|---|---|---|
| main | 568KB | 169KB | Core app code (-14KB) |
| index | 229KB | 70KB | ✅ Index route (-151KB, -40%) |
| vendor-web3 | 246KB | 75KB | viem, wagmi |
| vendor-radix | 152KB | 48KB | Radix UI components |
| vendor-tanstack | 99KB | 28KB | Query, Table, Virtual |
| init (perf) | 6KB | 2.5KB | Performance monitoring |
| styles | 123KB | 19KB | CSS (Tailwind) |
| i18n messages | ~66KB | ~28KB | 5 locale files |
| code-split chunks | 153KB | 54KB | Lazy-loaded components |
Total Client JS: ~1.64MB (gzip: ~494KB)
| Component | Size | Gzip |
|---|---|---|
| mobile-terminal | 46.7KB | 15.2KB |
| deposit-modal | 26.8KB | 8.6KB |
| positions-tab | 15.4KB | 5.0KB |
| trading-view-chart | 14.6KB | 5.2KB |
| orders-tab | 13.2KB | 5.3KB |
| global-settings-dialog | 10.2KB | 3.6KB |
| twap-tab | 6.6KB | 2.6KB |
| history-tab | 6.2KB | 2.5KB |
| funding-tab | 5.8KB | 2.4KB |
| balances-tab | 5.2KB | 2.2KB |
-
main.js (582KB) - Split by feature/route
- Trading components
- Chart components (recharts)
- Order entry forms
-
index.js (380KB) - Lazy load non-critical
- Modals/dialogs
- Settings panels
-
vendor-web3 (251KB) - Load on wallet connect
- Defer until user needs wallet features
-
Locale files - Load only user's language
- Architectural Issues - Rendering too many components upfront
- Virtualization - Must be manually implemented
- Data Fetching Patterns - N+1 queries, waterfalls
- WebSocket Flooding - Batching still needed
- Heavy Computations - Web Workers still needed
- React Compiler - Auto memoization (already enabled ✅)
- useTransition - Non-blocking UI updates
- useDeferredValue - Deferred expensive renders
- Suspense - Granular loading states
- Performance Tracks - Chrome DevTools integration