feat: implement lazy loading for routes and add a loading component in App.tsx; configure manual chunks in Vite for optimized builds
Some checks failed
Frontend CI / lint (push) Failing after 18s
Frontend CI / build (push) Has been skipped

This commit is contained in:
JSC
2025-10-04 15:44:33 +02:00
parent b303d2f5cf
commit 4352e4c792
2 changed files with 185 additions and 113 deletions

View File

@@ -1,23 +1,38 @@
import { lazy, Suspense } from 'react'
import { Navigate, Route, Routes } from 'react-router' import { Navigate, Route, Routes } from 'react-router'
import { LocaleProvider } from './components/LocaleProvider' import { LocaleProvider } from './components/LocaleProvider'
import { ThemeProvider } from './components/ThemeProvider' import { ThemeProvider } from './components/ThemeProvider'
import { Toaster } from './components/ui/sonner' import { Toaster } from './components/ui/sonner'
import { AuthProvider, useAuth } from './contexts/AuthContext' import { AuthProvider, useAuth } from './contexts/AuthContext'
import { SocketProvider } from './contexts/SocketContext' import { SocketProvider } from './contexts/SocketContext'
import { AccountPage } from './pages/AccountPage'
import { AuthCallbackPage } from './pages/AuthCallbackPage' // Lazy load all pages for code splitting
import { DashboardPage } from './pages/DashboardPage' const AccountPage = lazy(() => import('./pages/AccountPage').then(m => ({ default: m.AccountPage })))
import { ExtractionsPage } from './pages/ExtractionsPage' const AuthCallbackPage = lazy(() => import('./pages/AuthCallbackPage').then(m => ({ default: m.AuthCallbackPage })))
import { LoginPage } from './pages/LoginPage' const DashboardPage = lazy(() => import('./pages/DashboardPage').then(m => ({ default: m.DashboardPage })))
import { PlaylistEditPage } from './pages/PlaylistEditPage' const ExtractionsPage = lazy(() => import('./pages/ExtractionsPage').then(m => ({ default: m.ExtractionsPage })))
import { PlaylistsPage } from './pages/PlaylistsPage' const LoginPage = lazy(() => import('./pages/LoginPage').then(m => ({ default: m.LoginPage })))
import { RegisterPage } from './pages/RegisterPage' const PlaylistEditPage = lazy(() => import('./pages/PlaylistEditPage').then(m => ({ default: m.PlaylistEditPage })))
import { SchedulersPage } from './pages/SchedulersPage' const PlaylistsPage = lazy(() => import('./pages/PlaylistsPage').then(m => ({ default: m.PlaylistsPage })))
import { SequencerPage } from './pages/SequencerPage' const RegisterPage = lazy(() => import('./pages/RegisterPage').then(m => ({ default: m.RegisterPage })))
import { SoundsPage } from './pages/SoundsPage' const SchedulersPage = lazy(() => import('./pages/SchedulersPage').then(m => ({ default: m.SchedulersPage })))
import { TTSPage } from './pages/TTSPage' const SequencerPage = lazy(() => import('./pages/SequencerPage').then(m => ({ default: m.SequencerPage })))
import { SettingsPage } from './pages/admin/SettingsPage' const SoundsPage = lazy(() => import('./pages/SoundsPage').then(m => ({ default: m.SoundsPage })))
import { UsersPage } from './pages/admin/UsersPage' const TTSPage = lazy(() => import('./pages/TTSPage').then(m => ({ default: m.TTSPage })))
const SettingsPage = lazy(() => import('./pages/admin/SettingsPage').then(m => ({ default: m.SettingsPage })))
const UsersPage = lazy(() => import('./pages/admin/UsersPage').then(m => ({ default: m.UsersPage })))
// Loading component for lazy-loaded routes
function PageLoader() {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto mb-2"></div>
<p className="text-muted-foreground text-sm">Loading...</p>
</div>
</div>
)
}
function ProtectedRoute({ children }: { children: React.ReactNode }) { function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { user, loading } = useAuth() const { user, loading } = useAuth()
@@ -63,105 +78,107 @@ function AppRoutes() {
const { user } = useAuth() const { user } = useAuth()
return ( return (
<Routes> <Suspense fallback={<PageLoader />}>
<Route <Routes>
path="/login" <Route
element={user ? <Navigate to="/" replace /> : <LoginPage />} path="/login"
/> element={user ? <Navigate to="/" replace /> : <LoginPage />}
<Route />
path="/register" <Route
element={user ? <Navigate to="/" replace /> : <RegisterPage />} path="/register"
/> element={user ? <Navigate to="/" replace /> : <RegisterPage />}
<Route path="/auth/callback" element={<AuthCallbackPage />} /> />
<Route <Route path="/auth/callback" element={<AuthCallbackPage />} />
path="/" <Route
element={ path="/"
<ProtectedRoute> element={
<DashboardPage /> <ProtectedRoute>
</ProtectedRoute> <DashboardPage />
} </ProtectedRoute>
/> }
<Route />
path="/sounds" <Route
element={ path="/sounds"
<ProtectedRoute> element={
<SoundsPage /> <ProtectedRoute>
</ProtectedRoute> <SoundsPage />
} </ProtectedRoute>
/> }
<Route />
path="/playlists" <Route
element={ path="/playlists"
<ProtectedRoute> element={
<PlaylistsPage /> <ProtectedRoute>
</ProtectedRoute> <PlaylistsPage />
} </ProtectedRoute>
/> }
<Route />
path="/playlists/:id/edit" <Route
element={ path="/playlists/:id/edit"
<ProtectedRoute> element={
<PlaylistEditPage /> <ProtectedRoute>
</ProtectedRoute> <PlaylistEditPage />
} </ProtectedRoute>
/> }
<Route />
path="/extractions" <Route
element={ path="/extractions"
<ProtectedRoute> element={
<ExtractionsPage /> <ProtectedRoute>
</ProtectedRoute> <ExtractionsPage />
} </ProtectedRoute>
/> }
<Route />
path="/tts" <Route
element={ path="/tts"
<ProtectedRoute> element={
<TTSPage /> <ProtectedRoute>
</ProtectedRoute> <TTSPage />
} </ProtectedRoute>
/> }
<Route />
path="/sequencer" <Route
element={ path="/sequencer"
<ProtectedRoute> element={
<SequencerPage /> <ProtectedRoute>
</ProtectedRoute> <SequencerPage />
} </ProtectedRoute>
/> }
<Route />
path="/schedulers" <Route
element={ path="/schedulers"
<ProtectedRoute> element={
<SchedulersPage /> <ProtectedRoute>
</ProtectedRoute> <SchedulersPage />
} </ProtectedRoute>
/> }
<Route />
path="/account" <Route
element={ path="/account"
<ProtectedRoute> element={
<AccountPage /> <ProtectedRoute>
</ProtectedRoute> <AccountPage />
} </ProtectedRoute>
/> }
<Route />
path="/admin/users" <Route
element={ path="/admin/users"
<AdminRoute> element={
<UsersPage /> <AdminRoute>
</AdminRoute> <UsersPage />
} </AdminRoute>
/> }
<Route />
path="/admin/settings" <Route
element={ path="/admin/settings"
<AdminRoute> element={
<SettingsPage /> <AdminRoute>
</AdminRoute> <SettingsPage />
} </AdminRoute>
/> }
</Routes> />
</Routes>
</Suspense>
) )
} }

View File

@@ -25,6 +25,61 @@ export default defineConfig({
build: { build: {
outDir: 'dist', outDir: 'dist',
sourcemap: false, // Disable source maps in production for security sourcemap: false, // Disable source maps in production for security
rollupOptions: {
output: {
manualChunks: {
// React core
'react': ['react', 'react-dom', 'react-router'],
// UI library - Radix UI components
'radix-ui': [
'@radix-ui/react-avatar',
'@radix-ui/react-checkbox',
'@radix-ui/react-context-menu',
'@radix-ui/react-dialog',
'@radix-ui/react-dropdown-menu',
'@radix-ui/react-label',
'@radix-ui/react-popover',
'@radix-ui/react-progress',
'@radix-ui/react-scroll-area',
'@radix-ui/react-select',
'@radix-ui/react-separator',
'@radix-ui/react-slider',
'@radix-ui/react-slot',
'@radix-ui/react-switch',
'@radix-ui/react-tabs',
'@radix-ui/react-tooltip',
],
// Drag and drop
'dnd-kit': [
'@dnd-kit/core',
'@dnd-kit/sortable',
'@dnd-kit/utilities',
],
// Utilities
'utils': [
'clsx',
'tailwind-merge',
'class-variance-authority',
'date-fns',
],
// Other libraries
'misc': [
'recharts',
'socket.io-client',
'sonner',
'next-themes',
'cmdk',
'react-day-picker',
'@number-flow/react',
'lucide-react',
],
},
},
},
}, },
// Preview server configuration (for testing built version) // Preview server configuration (for testing built version)
preview: { preview: {