perf: add lazy loading for heavy components

- Use React.lazy for DataGrid, WeeklyGrid, and TopMovers
- Add Suspense with LoadingSpinner fallback for smooth transitions
- Enables code splitting for faster initial page load
- Combined with previous O(n²) fix, should significantly improve performance
This commit is contained in:
Christian Vidal Wolf
2026-01-22 11:55:23 +01:00
parent fa69a68b57
commit 15f5b08c71
+18 -8
View File
@@ -1,11 +1,7 @@
import React, { useState, useMemo, useEffect, useCallback } from 'react'; import React, { useState, useMemo, useEffect, useCallback, Suspense, lazy } from 'react';
import FileUpload from './components/FileUpload'; import FileUpload from './components/FileUpload';
import Dashboard from './components/Dashboard'; import Dashboard from './components/Dashboard';
import DataGrid from './components/DataGrid';
import WeeklyGrid from './components/WeeklyGrid';
import TopMovers from './components/TopMovers';
// import AdvertisingDashboard from './components/AdvertisingDashboard'; // Removed
import FilterBar from './components/FilterBar'; import FilterBar from './components/FilterBar';
import AIChat from './components/AIChat'; import AIChat from './components/AIChat';
import CrazeLogo from './components/CrazeLogo'; import CrazeLogo from './components/CrazeLogo';
@@ -15,6 +11,18 @@ import { queryGemini } from './services/geminiService';
import { ChartIcon, TableIcon, UploadIcon, DownloadIcon, CloseIcon, TrendingIcon } from './components/Icons'; import { ChartIcon, TableIcon, UploadIcon, DownloadIcon, CloseIcon, TrendingIcon } from './components/Icons';
import { loadSalesData, saveSalesData, clearSalesData, loadAdsData, saveAdsData, clearAdsData } from './services/storage'; import { loadSalesData, saveSalesData, clearSalesData, loadAdsData, saveAdsData, clearAdsData } from './services/storage';
// Lazy load heavy components for better initial performance
const DataGrid = lazy(() => import('./components/DataGrid'));
const WeeklyGrid = lazy(() => import('./components/WeeklyGrid'));
const TopMovers = lazy(() => import('./components/TopMovers'));
// Loading fallback component
const LoadingSpinner = () => (
<div className="flex items-center justify-center h-96">
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-indigo-500"></div>
</div>
);
// New Refresh Icon // New Refresh Icon
const RefreshIcon = ({ className }: { className?: string }) => ( const RefreshIcon = ({ className }: { className?: string }) => (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className={className || "w-5 h-5"}> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className={className || "w-5 h-5"}>
@@ -417,9 +425,11 @@ const App: React.FC = () => {
adsData={filteredAdsData} adsData={filteredAdsData}
/> />
)} )}
{view === 'table' && <DataGrid data={combinedAdsData} hasCustomerFilter={filters.customer.length > 0} adsData={filteredAdsData} />} <Suspense fallback={<LoadingSpinner />}>
{view === 'weekly' && <WeeklyGrid data={combinedAdsData} />} {view === 'table' && <DataGrid data={combinedAdsData} hasCustomerFilter={filters.customer.length > 0} adsData={filteredAdsData} />}
{view === 'movers' && <TopMovers data={filteredData} />} {view === 'weekly' && <WeeklyGrid data={combinedAdsData} />}
{view === 'movers' && <TopMovers data={filteredData} />}
</Suspense>
</div> </div>
</> </>
)} )}