Add route-based code splitting and loading skeletons

- Lazy-load Dashboard, Comparison, Slides via React.lazy + Suspense
- Main bundle reduced from 606KB to 256KB
- Replace full-screen spinner with skeleton cards during load
- Skeleton used for both initial data fetch and route transitions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
fahed
2026-03-25 18:10:42 +03:00
parent cd1e395ffa
commit 30ea4b6ecb
3 changed files with 113 additions and 12 deletions

View File

@@ -1,8 +1,10 @@
import React, { useState, useEffect, useCallback, ReactNode } from 'react';
import React, { useState, useEffect, useCallback, ReactNode, lazy, Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route, Link, useLocation } from 'react-router-dom';
import Dashboard from './components/Dashboard';
import Comparison from './components/Comparison';
import Slides from './components/Slides';
const Dashboard = lazy(() => import('./components/Dashboard'));
const Comparison = lazy(() => import('./components/Comparison'));
const Slides = lazy(() => import('./components/Slides'));
import LoadingSkeleton from './components/shared/LoadingSkeleton';
import { fetchData, getCacheStatus, refreshData } from './services/dataService';
import { useLanguage } from './contexts/LanguageContext';
import type { MuseumRecord, CacheStatus, DataErrorType } from './types';
@@ -83,9 +85,8 @@ function App() {
if (loading) {
return (
<div className="loading-container" dir={dir}>
<div className="loading-spinner"></div>
<p>{t('app.loading')}</p>
<div className="app" dir={dir}>
<LoadingSkeleton />
</div>
);
}
@@ -191,11 +192,13 @@ function App() {
</div>
</nav>
<Routes>
<Route path="/" element={<Dashboard data={data} showDataLabels={showDataLabels} setShowDataLabels={setShowDataLabels} includeVAT={includeVAT} setIncludeVAT={setIncludeVAT} />} />
<Route path="/comparison" element={<Comparison data={data} showDataLabels={showDataLabels} setShowDataLabels={setShowDataLabels} includeVAT={includeVAT} setIncludeVAT={setIncludeVAT} />} />
<Route path="/slides" element={<Slides data={data} />} />
</Routes>
<Suspense fallback={<LoadingSkeleton />}>
<Routes>
<Route path="/" element={<Dashboard data={data} showDataLabels={showDataLabels} setShowDataLabels={setShowDataLabels} includeVAT={includeVAT} setIncludeVAT={setIncludeVAT} />} />
<Route path="/comparison" element={<Comparison data={data} showDataLabels={showDataLabels} setShowDataLabels={setShowDataLabels} includeVAT={includeVAT} setIncludeVAT={setIncludeVAT} />} />
<Route path="/slides" element={<Slides data={data} />} />
</Routes>
</Suspense>
{/* Mobile Bottom Navigation */}
<nav className="mobile-nav">