perf(frontend): 路由级代码分割 — React.lazy + Suspense
将所有页面组件改为按路由懒加载,Layout 组件保持静态导入。 新增 LoadingSpinner 作为 Suspense 回退组件。 html5-qrcode (~200KB) 和 antd 仅在访问扫码/管理后台路由时加载。
This commit is contained in:
@ -1,20 +1,26 @@
|
||||
import { Suspense, lazy } from "react";
|
||||
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
|
||||
import { App as AntApp } from "antd";
|
||||
|
||||
import { ToastProvider } from "./components/ui/Toast";
|
||||
import { AuthProvider } from "./contexts/AuthContext";
|
||||
import AppLayout from "./components/layout/AppLayout";
|
||||
import ScanPage from "./pages/ScanPage";
|
||||
import MyTasksPage from "./pages/MyTasksPage";
|
||||
import NotificationsPage from "./pages/NotificationsPage";
|
||||
import ProfilePage from "./pages/ProfilePage";
|
||||
import LoadingSpinner from "./components/ui/LoadingSpinner";
|
||||
|
||||
// Layout 组件静态导入(始终需要,体积小)
|
||||
import AppLayout from "./components/layout/AppLayout";
|
||||
import AdminLayout from "./components/layout/AdminLayout";
|
||||
import AdminLoginPage from "./pages/admin/AdminLoginPage";
|
||||
import AdminDashboard from "./pages/admin/AdminDashboard";
|
||||
import AdminProductsPage from "./pages/admin/AdminProductsPage";
|
||||
import AdminTasksPage from "./pages/admin/AdminTasksPage";
|
||||
import AdminPrintConfigPage from "./pages/admin/AdminPrintConfigPage";
|
||||
|
||||
// 🚀 路由级代码分割 — 按需懒加载页面组件
|
||||
const ScanPage = lazy(() => import("./pages/ScanPage"));
|
||||
const MyTasksPage = lazy(() => import("./pages/MyTasksPage"));
|
||||
const NotificationsPage = lazy(() => import("./pages/NotificationsPage"));
|
||||
const ProfilePage = lazy(() => import("./pages/ProfilePage"));
|
||||
|
||||
const AdminLoginPage = lazy(() => import("./pages/admin/AdminLoginPage"));
|
||||
const AdminDashboard = lazy(() => import("./pages/admin/AdminDashboard"));
|
||||
const AdminProductsPage = lazy(() => import("./pages/admin/AdminProductsPage"));
|
||||
const AdminTasksPage = lazy(() => import("./pages/admin/AdminTasksPage"));
|
||||
const AdminPrintConfigPage = lazy(() => import("./pages/admin/AdminPrintConfigPage"));
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@ -22,28 +28,30 @@ export default function App() {
|
||||
<ToastProvider>
|
||||
<AuthProvider>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
{/* 移动端 */}
|
||||
<Route path="/" element={<Navigate to="/scan" replace />} />
|
||||
<Route element={<AppLayout />}>
|
||||
<Route path="/scan" element={<ScanPage />} />
|
||||
<Route path="/tasks" element={<MyTasksPage />} />
|
||||
<Route path="/notifications" element={<NotificationsPage />} />
|
||||
<Route path="/profile" element={<ProfilePage />} />
|
||||
</Route>
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
<Routes>
|
||||
{/* 移动端 */}
|
||||
<Route path="/" element={<Navigate to="/admin/dashboard" replace />} />
|
||||
<Route element={<AppLayout />}>
|
||||
<Route path="/scan" element={<ScanPage />} />
|
||||
<Route path="/tasks" element={<MyTasksPage />} />
|
||||
<Route path="/notifications" element={<NotificationsPage />} />
|
||||
<Route path="/profile" element={<ProfilePage />} />
|
||||
</Route>
|
||||
|
||||
{/* PC 管理端 — 登录页(独立,无侧边栏) */}
|
||||
<Route path="/admin/login" element={<AdminLoginPage />} />
|
||||
{/* PC 管理端 — 登录页(独立,无侧边栏) */}
|
||||
<Route path="/admin/login" element={<AdminLoginPage />} />
|
||||
|
||||
{/* PC 管理端 — 需要登录 */}
|
||||
<Route path="/admin" element={<Navigate to="/admin/dashboard" replace />} />
|
||||
<Route element={<AdminLayout />}>
|
||||
<Route path="/admin/dashboard" element={<AdminDashboard />} />
|
||||
<Route path="/admin/products" element={<AdminProductsPage />} />
|
||||
<Route path="/admin/tasks" element={<AdminTasksPage />} />
|
||||
<Route path="/admin/print-config" element={<AdminPrintConfigPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
{/* PC 管理端 — 需要登录 */}
|
||||
<Route path="/admin" element={<Navigate to="/admin/dashboard" replace />} />
|
||||
<Route element={<AdminLayout />}>
|
||||
<Route path="/admin/dashboard" element={<AdminDashboard />} />
|
||||
<Route path="/admin/products" element={<AdminProductsPage />} />
|
||||
<Route path="/admin/tasks" element={<AdminTasksPage />} />
|
||||
<Route path="/admin/print-config" element={<AdminPrintConfigPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</BrowserRouter>
|
||||
</AuthProvider>
|
||||
</ToastProvider>
|
||||
|
||||
10
frontend/src/components/ui/LoadingSpinner.tsx
Normal file
10
frontend/src/components/ui/LoadingSpinner.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { Loader2 } from "lucide-react";
|
||||
|
||||
/** 全局路由懒加载回退组件 */
|
||||
export default function LoadingSpinner() {
|
||||
return (
|
||||
<div className="flex items-center justify-center py-32">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-blue-500" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user