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"],
+ },
},
},
},