From 5962c6d04b241c23bb2a2290db25a06211a86e40 Mon Sep 17 00:00:00 2001 From: nbb <43722192+nbb2025@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:16:05 +0800 Subject: [PATCH] feat: optimize initial load performance by implementing lazy loading and code splitting (#4445) --- web/src/router/index.tsx | 129 +++++++++++++++++++++++++++++---------- web/vite.config.ts | 15 ++++- 2 files changed, 112 insertions(+), 32 deletions(-) diff --git a/web/src/router/index.tsx b/web/src/router/index.tsx index 52c7fc73..1bf26197 100644 --- a/web/src/router/index.tsx +++ b/web/src/router/index.tsx @@ -1,23 +1,26 @@ +import { Suspense, lazy } from "react"; import { createBrowserRouter } from "react-router-dom"; import App from "@/App"; import HomeLayout from "@/layouts/HomeLayout"; import RootLayout from "@/layouts/RootLayout"; -import About from "@/pages/About"; -import AdminSignIn from "@/pages/AdminSignIn"; -import Archived from "@/pages/Archived"; -import AuthCallback from "@/pages/AuthCallback"; -import Explore from "@/pages/Explore"; import Home from "@/pages/Home"; -import Inboxes from "@/pages/Inboxes"; -import MemoDetail from "@/pages/MemoDetail"; -import NotFound from "@/pages/NotFound"; -import PermissionDenied from "@/pages/PermissionDenied"; -import Resources from "@/pages/Resources"; -import Setting from "@/pages/Setting"; -import SignIn from "@/pages/SignIn"; -import SignUp from "@/pages/SignUp"; -import UserProfile from "@/pages/UserProfile"; -import MemoDetailRedirect from "./MemoDetailRedirect"; +import Loading from "@/pages/Loading"; + +const About = lazy(() => import("@/pages/About")); +const AdminSignIn = lazy(() => import("@/pages/AdminSignIn")); +const Archived = lazy(() => import("@/pages/Archived")); +const AuthCallback = lazy(() => import("@/pages/AuthCallback")); +const Explore = lazy(() => import("@/pages/Explore")); +const Inboxes = lazy(() => import("@/pages/Inboxes")); +const MemoDetail = lazy(() => import("@/pages/MemoDetail")); +const NotFound = lazy(() => import("@/pages/NotFound")); +const PermissionDenied = lazy(() => import("@/pages/PermissionDenied")); +const Resources = lazy(() => import("@/pages/Resources")); +const Setting = lazy(() => import("@/pages/Setting")); +const SignIn = lazy(() => import("@/pages/SignIn")); +const SignUp = lazy(() => import("@/pages/SignUp")); +const UserProfile = lazy(() => import("@/pages/UserProfile")); +const MemoDetailRedirect = lazy(() => import("./MemoDetailRedirect")); export enum Routes { ROOT = "/", @@ -40,19 +43,35 @@ const router = createBrowserRouter([ children: [ { path: "", - element: , + element: ( + }> + + + ), }, { path: "admin", - element: , + element: ( + }> + + + ), }, { path: "signup", - element: , + element: ( + }> + + + ), }, { path: "callback", - element: , + element: ( + }> + + + ), }, ], }, @@ -69,54 +88,102 @@ const router = createBrowserRouter([ }, { path: Routes.EXPLORE, - element: , + element: ( + }> + + + ), }, { path: Routes.ARCHIVED, - element: , + element: ( + }> + + + ), }, { path: "u/:username", - element: , + element: ( + }> + + + ), }, ], }, { path: Routes.RESOURCES, - element: , + element: ( + }> + + + ), }, { path: Routes.INBOX, - element: , + element: ( + }> + + + ), }, { path: Routes.SETTING, - element: , + element: ( + }> + + + ), }, { path: "memos/:uid", - element: , + element: ( + }> + + + ), }, { path: Routes.ABOUT, - element: , + element: ( + }> + + + ), }, // Redirect old path to new path. { path: "m/:uid", - element: , + element: ( + }> + + + ), }, { path: "403", - element: , + element: ( + }> + + + ), }, { path: "404", - element: , + element: ( + }> + + + ), }, { path: "*", - element: , + element: ( + }> + + + ), }, ], }, diff --git a/web/vite.config.ts b/web/vite.config.ts index f09f36af..676cbc9e 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -44,8 +44,21 @@ export default defineConfig({ rollupOptions: { output: { entryFileNames: "app.[hash].js", - chunkFileNames: "assets/chunk-vendors.[hash].js", + chunkFileNames: (chunkInfo) => { + const facadeModuleId = chunkInfo.facadeModuleId ? chunkInfo.facadeModuleId.split("/") : []; + const name = facadeModuleId[facadeModuleId.length - 2] || "[name]"; + return `assets/${name}/[name].[hash].js`; + }, assetFileNames: "assets/[name].[hash][extname]", + manualChunks: { + "react-vendor": ["react", "react-dom", "react-router-dom"], + "mui-vendor": ["@mui/joy", "@emotion/react", "@emotion/styled"], + "utils-vendor": ["dayjs", "lodash-es", "mobx", "mobx-react-lite"], + "katex-vendor": ["katex"], + "highlight-vendor": ["highlight.js"], + "mermaid-vendor": ["mermaid"], + "map-vendor": ["leaflet", "react-leaflet"], + }, }, }, },