feat: implement lazy loading for routes and add a loading component in App.tsx; configure manual chunks in Vite for optimized builds
This commit is contained in:
243
src/App.tsx
243
src/App.tsx
@@ -1,23 +1,38 @@
|
||||
import { lazy, Suspense } from 'react'
|
||||
import { Navigate, Route, Routes } from 'react-router'
|
||||
import { LocaleProvider } from './components/LocaleProvider'
|
||||
import { ThemeProvider } from './components/ThemeProvider'
|
||||
import { Toaster } from './components/ui/sonner'
|
||||
import { AuthProvider, useAuth } from './contexts/AuthContext'
|
||||
import { SocketProvider } from './contexts/SocketContext'
|
||||
import { AccountPage } from './pages/AccountPage'
|
||||
import { AuthCallbackPage } from './pages/AuthCallbackPage'
|
||||
import { DashboardPage } from './pages/DashboardPage'
|
||||
import { ExtractionsPage } from './pages/ExtractionsPage'
|
||||
import { LoginPage } from './pages/LoginPage'
|
||||
import { PlaylistEditPage } from './pages/PlaylistEditPage'
|
||||
import { PlaylistsPage } from './pages/PlaylistsPage'
|
||||
import { RegisterPage } from './pages/RegisterPage'
|
||||
import { SchedulersPage } from './pages/SchedulersPage'
|
||||
import { SequencerPage } from './pages/SequencerPage'
|
||||
import { SoundsPage } from './pages/SoundsPage'
|
||||
import { TTSPage } from './pages/TTSPage'
|
||||
import { SettingsPage } from './pages/admin/SettingsPage'
|
||||
import { UsersPage } from './pages/admin/UsersPage'
|
||||
|
||||
// Lazy load all pages for code splitting
|
||||
const AccountPage = lazy(() => import('./pages/AccountPage').then(m => ({ default: m.AccountPage })))
|
||||
const AuthCallbackPage = lazy(() => import('./pages/AuthCallbackPage').then(m => ({ default: m.AuthCallbackPage })))
|
||||
const DashboardPage = lazy(() => import('./pages/DashboardPage').then(m => ({ default: m.DashboardPage })))
|
||||
const ExtractionsPage = lazy(() => import('./pages/ExtractionsPage').then(m => ({ default: m.ExtractionsPage })))
|
||||
const LoginPage = lazy(() => import('./pages/LoginPage').then(m => ({ default: m.LoginPage })))
|
||||
const PlaylistEditPage = lazy(() => import('./pages/PlaylistEditPage').then(m => ({ default: m.PlaylistEditPage })))
|
||||
const PlaylistsPage = lazy(() => import('./pages/PlaylistsPage').then(m => ({ default: m.PlaylistsPage })))
|
||||
const RegisterPage = lazy(() => import('./pages/RegisterPage').then(m => ({ default: m.RegisterPage })))
|
||||
const SchedulersPage = lazy(() => import('./pages/SchedulersPage').then(m => ({ default: m.SchedulersPage })))
|
||||
const SequencerPage = lazy(() => import('./pages/SequencerPage').then(m => ({ default: m.SequencerPage })))
|
||||
const SoundsPage = lazy(() => import('./pages/SoundsPage').then(m => ({ default: m.SoundsPage })))
|
||||
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 }) {
|
||||
const { user, loading } = useAuth()
|
||||
@@ -63,105 +78,107 @@ function AppRoutes() {
|
||||
const { user } = useAuth()
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path="/login"
|
||||
element={user ? <Navigate to="/" replace /> : <LoginPage />}
|
||||
/>
|
||||
<Route
|
||||
path="/register"
|
||||
element={user ? <Navigate to="/" replace /> : <RegisterPage />}
|
||||
/>
|
||||
<Route path="/auth/callback" element={<AuthCallbackPage />} />
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<DashboardPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/sounds"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SoundsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/playlists"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<PlaylistsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/playlists/:id/edit"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<PlaylistEditPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/extractions"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<ExtractionsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/tts"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<TTSPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/sequencer"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SequencerPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/schedulers"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SchedulersPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/account"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AccountPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/admin/users"
|
||||
element={
|
||||
<AdminRoute>
|
||||
<UsersPage />
|
||||
</AdminRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/admin/settings"
|
||||
element={
|
||||
<AdminRoute>
|
||||
<SettingsPage />
|
||||
</AdminRoute>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
<Suspense fallback={<PageLoader />}>
|
||||
<Routes>
|
||||
<Route
|
||||
path="/login"
|
||||
element={user ? <Navigate to="/" replace /> : <LoginPage />}
|
||||
/>
|
||||
<Route
|
||||
path="/register"
|
||||
element={user ? <Navigate to="/" replace /> : <RegisterPage />}
|
||||
/>
|
||||
<Route path="/auth/callback" element={<AuthCallbackPage />} />
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<DashboardPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/sounds"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SoundsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/playlists"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<PlaylistsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/playlists/:id/edit"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<PlaylistEditPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/extractions"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<ExtractionsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/tts"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<TTSPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/sequencer"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SequencerPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/schedulers"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SchedulersPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/account"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AccountPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/admin/users"
|
||||
element={
|
||||
<AdminRoute>
|
||||
<UsersPage />
|
||||
</AdminRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/admin/settings"
|
||||
element={
|
||||
<AdminRoute>
|
||||
<SettingsPage />
|
||||
</AdminRoute>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,61 @@ export default defineConfig({
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
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: {
|
||||
|
||||
Reference in New Issue
Block a user