Skip to content

Latest commit

 

History

History
405 lines (325 loc) · 12.2 KB

File metadata and controls

405 lines (325 loc) · 12.2 KB

FinGuard Frontend Structure & Code Splitting Analysis

Executive Summary

The frontend is a React 19 application built with Vite and TypeScript. It lacks code splitting and lazy loading, resulting in a large initial bundle. The application has 15 pages and 6 components with two heavy chart-based components using Recharts.


1. Pages & Components Overview

15 Pages:

  1. Dashboard.tsx - Main dashboard with metrics and CashFlowChart
  2. Forecast.tsx - Cash flow forecasting with ForecastChart (Monte Carlo)
  3. DecisionEngine.tsx - Report generation and payment execution
  4. Transactions.tsx - Transaction management with CSV import
  5. Invoices.tsx - Invoice registry with vendor table
  6. ActionComposer.tsx - Email/WhatsApp messaging compose
  7. VendorDetail.tsx - Individual vendor detail view
  8. Settings.tsx - System configuration and API integrations
  9. Preferences.tsx - User preferences and notification settings
  10. Profile.tsx - User profile management and editing
  11. Landing.tsx - Public landing page
  12. Login.tsx - Authentication login
  13. Register.tsx - User registration
  14. Onboarding.tsx - New user onboarding flow
  15. Help.tsx - FAQ and documentation

6 Reusable Components:

  1. CashFlowChart.tsx - Heavy chart component (Recharts)
  2. ForecastChart.tsx - Heavy chart component (Recharts)
  3. Layout.tsx - Main layout wrapper with navigation
  4. NotificationCenter.tsx - Notification dropdown
  5. ProfileDropdown.tsx - Profile menu dropdown
  6. ProtectedRoute.tsx - Route protection wrapper

2. Pages/Components with Graphs & Charts

✅ Pages Using Charts:

Page Chart Type Library Size Impact Notes
Dashboard CashFlowChart (ComposedChart) Recharts HIGH 📊 Multiple series (current, w1, w2, w3, expected, forecast, risk)
Forecast ForecastChart (ComposedChart + Area) Recharts HIGH 📈 Monte Carlo analysis with P10, P50, P90 bands

📊 Chart Component Details:

CashFlowChart.tsx:

  • Uses: ComposedChart, Bar, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ReferenceLine
  • Features: Live data polling (10s interval), filtering, date range selection, CSV/PDF export
  • Estimated Size: ~50-80KB (minified)

ForecastChart.tsx:

  • Uses: ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ReferenceLine
  • Features: Live data polling (15s interval), time range selection, metrics display
  • Estimated Size: ~50-80KB (minified)

Non-Chart Pages:

  • DecisionEngine - Complex modals, report generation, payment execution
  • Invoices - Heavy table rendering (8-24 rows)
  • Transactions - CSV file upload, AI draft generation
  • Settings - Multiple connected accounts, API configuration
  • Preferences - Three-tab interface (notifications, display, financial)

3. Current Import Patterns

Main App Structure:

App.tsx
├── Landing.tsx (public)
├── Login.tsx (public)
├── Register.tsx (public)
├── Help.tsx (public)
└── ProtectedRoute
    ├── Onboarding.tsx
    └── Layout
        ├── Dashboard (with CashFlowChart)
        ├── Transactions
        ├── Forecast (with ForecastChart)
        ├── DecisionEngine
        ├── ActionComposer
        ├── Invoices
        ├── Vendor/:vendorName
        ├── Settings
        ├── Profile
        ├── Preferences

Import Types:

Static Imports (Bundle Impact):

  • All 15 pages imported at app root in App.tsx
  • All 6 components imported directly
  • Recharts fully loaded even when not viewing chart pages
  • html2canvas & jsPDF loaded at compile time

Dynamic Imports (Already Optimized):

  • exportElementToPdf() function uses dynamic imports:
    const [{ default: html2canvas }, { jsPDF }] = await Promise.all([
      import('html2canvas'),
      import('jspdf')
    ]);

4. Heavy Components & Modules for Lazy Loading

🔴 HIGH PRIORITY - Lazy Load These:

Chart Libraries:

Recharts Package Size:
- recharts: ~150-200KB (minified)
- Used only in: Dashboard, Forecast (2 of 15 pages = 13%)
- Bundle Impact: Loaded for all users, used by 2 pages

PDF Export Utilities:

html2canvas: ~100KB
jsPDF: ~200KB
Total: ~300KB (minified)

Current Status: ✅ Already using dynamic imports in lib/export.ts
Impact: Only loaded when user clicks "Export to PDF"
Recommendation: Good pattern - follow this for other heavy modules

Pages for Code Splitting (Estimated Sizes):

Page Size Est. Why Lazy Load Priority
Forecast 80-120KB Large chart + table + metrics 🔴 HIGH
Dashboard 50-100KB CashFlowChart + modals 🔴 HIGH
DecisionEngine 60-90KB Complex interface, modals 🔴 HIGH
Invoices 40-70KB Large table rendering 🟡 MEDIUM
Transactions 40-70KB Table + CSV upload + AI 🟡 MEDIUM
Settings 30-50KB Forms + account list 🟡 MEDIUM
Preferences 30-50KB Tab interface + forms 🟡 MEDIUM
ActionComposer 25-40KB Forms + API calls 🟢 LOW
VendorDetail 20-40KB Detail view + metrics 🟢 LOW
Profile 20-40KB Form + edit mode 🟢 LOW
Help 15-25KB FAQ static content 🟢 LOW
Landing 15-25KB Static content 🟢 LOW
Login 15-25KB Form + auth 🟢 LOW
Register 15-25KB Form + validation 🟢 LOW
Onboarding 15-25KB Form + auth 🟢 LOW

📦 Dependencies Impact Summary:

Current bundle will include:
✓ react (core) - 50KB
✓ react-dom - 70KB
✓ react-router-dom - 50KB
✓ recharts - 150-200KB (used by 2 pages!)
✓ tailwindcss - ~30KB compiled
✓ All 15 pages statically imported
✓ All 6 components statically imported
✓ html2canvas - already lazy (good!)
✓ jsPDF - already lazy (good!)

Estimated Initial Bundle: 500-800KB (before gzip)
After gzip: ~150-250KB

5. Code Splitting Patterns

✅ Current Good Practices:

  1. Dynamic imports for PDF generation (export.ts):

    // Only loaded when PDF export is triggered
    const [{ default: html2canvas }, { jsPDF }] = await Promise.all([
      import('html2canvas'),
      import('jspdf')
    ]);
  2. API abstraction layer (api.ts):

    • Clean fetch wrapper with error handling
    • Single point for CORS and authentication
    • Makes API methods easily tree-shakeable

❌ Current Issues:

  1. No route-based code splitting - All pages in initial bundle
  2. Recharts loaded for all users - Only needed by 2 pages
  3. No component lazy loading - No React.lazy()
  4. Vite config missing optimization - No build optimizations

Configuration Details:

Vite Config (vite.config.ts):

// Current - no optimizations
export default defineConfig({
  plugins: [react()],
})

// Missing:
// - build.rollupOptions.output.manualChunks
// - build.chunkSizeWarningLimit
// - build.minify configuration

6. Bundle Size Indicators

Estimated Bundle Breakdown (Current):

Initial Load (No Code Splitting):
├── React Core: ~50KB
├── React DOM: ~70KB
├── React Router: ~50KB
├── Recharts: ~150-200KB ⚠️ (not used by 87% of pages)
├── Page Components: ~250-350KB
├── UI Components: ~50KB
├── TailwindCSS (compiled): ~30KB
├── Other utilities: ~50KB
└── Fonts (@fontsource): ~150KB
Total: ~900KB-1.2MB (uncompressed)
After Gzip: ~250-350KB

Per-Page Load Time Impact:
- First Contentful Paint (FCP): ~2-3s
- Time to Interactive (TTI): ~4-6s

Optimized Bundle (With Recommended Changes):

Initial Load:
├── React Core + Router + DOM: ~170KB
├── Layout + Navigation: ~30KB
├── Auth Context: ~10KB
├── Common Utilities: ~50KB
├── Fonts: ~150KB
└── Inline Landing Page: ~20KB
Total: ~430KB (uncompressed)
After Gzip: ~130-150KB

Lazy Loaded (On-Demand):
├── Dashboard chunk: ~80KB
├── Forecast chunk: ~100KB
├── DecisionEngine chunk: ~70KB
├── Recharts (only for chart pages): ~150KB
└── Other pages: ~250KB

Performance Improvement: 65-70% reduction in initial bundle size


7. Recommendations Summary

🔴 Critical (Implement First):

  1. Lazy load pages using Route-based code splitting

    • Use React.lazy() + Suspense
    • Apply to all 15 pages
    • Expected savings: 250-350KB
  2. Lazy load chart components

    • Load Recharts only for Dashboard/Forecast
    • Expected savings: 150-200KB
  3. Extract chart code into separate chunks

    • CashFlowChart can be tree-shaken
    • ForecastChart can be tree-shaken

🟡 High Priority:

  1. Optimize vite.config.ts

    • Add manual chunk splitting
    • Configure minification
    • Set chunk size warnings
  2. Lazy load heavy pages

    • Invoices, Transactions, Settings, Preferences
    • Expected savings: 100-150KB

🟢 Medium Priority:

  1. Review export patterns

    • Keep dynamic imports for PDF (already good)
    • Add dynamic imports for other utilities
  2. Monitor bundle size

    • Add rollup-plugin-visualizer
    • Set up bundle size checks in CI/CD

8. File Structure Summary

frontend/src/
├── pages/           [15 pages - all heavy]
│   ├── Dashboard.tsx       [Heavy - Chart]
│   ├── Forecast.tsx        [Heavy - Chart]
│   ├── DecisionEngine.tsx  [Heavy - Modals]
│   ├── Invoices.tsx        [Medium - Table]
│   ├── Transactions.tsx    [Medium - Upload]
│   ├── Settings.tsx        [Medium - Forms]
│   ├── Preferences.tsx     [Medium - Tabs]
│   └── ... 8 more pages
│
├── components/      [6 reusable components]
│   ├── CashFlowChart.tsx   [Heavy - Recharts]
│   ├── ForecastChart.tsx   [Heavy - Recharts]
│   ├── Layout.tsx          [Core navigation]
│   └── ... 3 more
│
├── lib/
│   ├── api.ts              [API abstraction - good]
│   ├── export.ts           [Dynamic imports - good]
│   └── supabaseClient.ts
│
└── context/
    └── AuthContext.tsx     [Auth state - core]

9. Dependencies Analysis

Production Dependencies:

{
  "recharts": "^3.8.1",           // 🔴 150-200KB - Lazy load!
  "react-router-dom": "^7.13.2",  // 50KB - Core
  "react": "^19.2.4",             // 50KB - Core
  "react-dom": "^19.2.4",         // 70KB - Core
  "html2canvas": "^1.4.1",        // ✅ Already lazy-loaded
  "jspdf": "^3.0.3",              // ✅ Already lazy-loaded
  "lucide-react": "^1.6.0",       // 20-30KB - Icon library
  "@fontsource/*": "^5.x.x",      // 150KB total - Fonts
  "tailwind-merge": "^3.5.0",     // ~5KB
  "clsx": "^2.1.1"                // ~2KB
}

Key Insights:

  • No Chart.js - Using Recharts (good choice)
  • No heavy UI frameworks - Using TailwindCSS (good)
  • Service worker: None detected
  • PWA features: Not implemented

Performance Metrics

Current Estimated:

  • Lighthouse Performance Score: 50-60/100
  • First Contentful Paint (FCP): 2-3 seconds
  • Time to Interactive (TTI): 4-6 seconds
  • Total Blocking Time (TBT): 300-500ms

After Lazy Loading Implementation:

  • Lighthouse Performance Score: 75-85/100
  • First Contentful Paint (FCP): 1-1.5 seconds (40-50% improvement)
  • Time to Interactive (TTI): 2-3 seconds (50-60% improvement)
  • Total Blocking Time (TBT): 100-200ms

Code Examples Reference

Current Non-Optimized:

// App.tsx - All 15 pages loaded upfront
import Dashboard from './pages/Dashboard';
import Forecast from './pages/Forecast';
// ... all 15 pages imported

Already Optimized Pattern:

// lib/export.ts - Good dynamic import usage
const [{ default: html2canvas }, { jsPDF }] = await Promise.all([
  import('html2canvas'),
  import('jspdf')
]);

Next Steps

  1. Review session memory for previous implementation notes
  2. Create lazy loading implementation plan
  3. Set up bundle analysis tools
  4. Implement route-based code splitting
  5. Test performance improvements
  6. Update CI/CD with bundle size checks