From 949d3a37a01694adc015f4b4cda9a6326ff5ceba Mon Sep 17 00:00:00 2001 From: ApparentlyPlus Date: Thu, 16 Apr 2026 23:13:41 +0300 Subject: [PATCH] feat: implement lazy loading for page components and optimize chunking in Vite config --- src/App.jsx | 39 +++++++++++++++++++++-------------- src/assets/ConfigRoutes.jsx | 41 +++++++++++++++---------------------- vite.config.js | 15 ++++++++++++++ 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 1b32ca5d..6854fdff 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -36,16 +36,25 @@ */ import { Routes, Route } from "react-router"; -import HomePage from "./pages/HomePage"; +import { lazy, Suspense, useEffect } from "react"; import Header from "./components/Header"; -import { useEffect } from "react"; -import FAQSettingsPage from "./pages/FAQSettingsPage"; -import AboutSettingsPage from "./pages/AboutSettingsPage"; import { Categories } from "./assets/ConfigRoutes"; import i18n from "./i18n"; -import Error404 from "./pages/Error404"; + +// Dynamic loading, no static jsx imports for pages +const pageComponents = Object.fromEntries( + Object.entries(import.meta.glob("./pages/*.{jsx,tsx}")).map(([path, loader]) => { + const name = path.replace(/^\.\/pages\//, "").replace(/\.(jsx|tsx)$/, ""); + return [name, lazy(loader)]; + }) +); + +const wrap = (Component, props = {}) => ( + +); + function App() { - console.log("hello", Categories); + console.log("hello", Categories); // Load the preferred language from local storage and set it initially useEffect(() => { const storedLanguage = localStorage.getItem('preferred_language'); @@ -53,28 +62,28 @@ function App() { i18n.changeLanguage(storedLanguage); } }, []); - const categoriesToDisplay = Categories.filter( - ({ hide }) => hide === false - ) + const categoriesToDisplay = Categories.filter(({ hide }) => hide === false); return ( }> - } /> + {categoriesToDisplay.map((category) => { + const PageComponent = pageComponents[category.page]; + if (!PageComponent) return null; return ( ); })} - } /> - } /> - } /> + + + ); } -export default App; +export default App; \ No newline at end of file diff --git a/src/assets/ConfigRoutes.jsx b/src/assets/ConfigRoutes.jsx index 9217063e..36bb474a 100644 --- a/src/assets/ConfigRoutes.jsx +++ b/src/assets/ConfigRoutes.jsx @@ -51,15 +51,6 @@ import { StackedBooksIcon, StudentInPCIcon, } from "./icons"; -import AnnouncementsPage from "../pages/AnnouncementPage"; -import ProfInfoPage from "../pages/ProfInfoPage"; -import RestaurantPage from "../pages/RestaurantPage"; -import ServicesPage from "../pages/ServicesPage"; -import GraduationPage from "../pages/GraduationPage"; -import LibraryPage from "../pages/LibraryPage"; -import FirstYearInfoPage from "../pages/FirstYearInfoPage"; -import SchedulePage from "../pages/SchedulePage"; -import MapPage from "../pages/MapPage"; import { FaUniversity } from "react-icons/fa"; import i18n from "../i18n"; export const Categories = [ @@ -72,7 +63,8 @@ export const Categories = [ requireSelection: true, position: 1, hide: false, - pageToDisplay: , + page: "SchedulePage", + pageProps: { semesterProp: true }, }, { title: "Open eClass", @@ -84,7 +76,7 @@ export const Categories = [ requireSelection: false, position: 2, hide: false, - pageToDisplay: null, + page: null, }, { title: i18n.t("restaurant"), @@ -95,7 +87,7 @@ export const Categories = [ requireSelection: false, position: 3, hide: false, - pageToDisplay: , + page: "RestaurantPage", }, { title: "Student Portal", @@ -106,7 +98,7 @@ export const Categories = [ requireSelection: false, position: 4, hide: false, - pageToDisplay: null, + page: null, }, { title: i18n.t("library"), @@ -117,7 +109,7 @@ export const Categories = [ span: 1, isExternal: false, requireSelection: false, - pageToDisplay: , + page: "LibraryPage", }, { @@ -129,7 +121,7 @@ export const Categories = [ requireSelection: false, position: 6, hide: false, - pageToDisplay: null, + page: null, }, { title: i18n.t("exams_schedule"), @@ -140,7 +132,8 @@ export const Categories = [ requireSelection: true, position: 7, hide: false, - pageToDisplay: , + page: "SchedulePage", + pageProps: { examsProp: true }, }, { title: i18n.t("academic_personnel"), @@ -151,7 +144,7 @@ export const Categories = [ requireSelection: true, position: 8, hide: false, - pageToDisplay: , + page: "ProfInfoPage", }, { title: i18n.t("map"), @@ -162,7 +155,7 @@ export const Categories = [ requireSelection: false, position: 9, hide: false, - pageToDisplay: , + page: "MapPage", }, { title: i18n.t("foititiki_merimna"), @@ -174,7 +167,7 @@ export const Categories = [ requireSelection: false, position: 10, hide: false, - pageToDisplay: null, + page: null, }, { title: i18n.t("freshmen_guides"), @@ -185,7 +178,7 @@ export const Categories = [ requireSelection: false, position: 11, hide: false, - pageToDisplay: , + page: "FirstYearInfoPage", }, { title: i18n.t("orkomosies"), @@ -196,7 +189,7 @@ export const Categories = [ requireSelection: true, position: 12, hide: false, - pageToDisplay: , + page: "GraduationPage", }, { title: i18n.t("other_services"), @@ -207,7 +200,7 @@ export const Categories = [ requireSelection: false, position: 13, hide: false, - pageToDisplay: , + page: "ServicesPage", }, { title: i18n.t("announcements"), @@ -218,7 +211,7 @@ export const Categories = [ requireSelection: true, position: 13, hide: false, - pageToDisplay: , + page: "AnnouncementPage", }, { title: i18n.t("masters"), @@ -237,6 +230,6 @@ export const Categories = [ requireSelection: false, position: 14, hide: false, - pageToDisplay: null, + page: null, }, ]; diff --git a/vite.config.js b/vite.config.js index 45bfb0d7..1fad1036 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,5 +9,20 @@ export default defineConfig({ port: 3000, open: true, host: true + }, + // Chunk js files by components for less overhead + build: { + rollupOptions: { + output: { + manualChunks: { + "vendor-react": ["react", "react-dom", "react-router"], + "vendor-chakra": ["@chakra-ui/react", "@chakra-ui/icons", "@emotion/react", "@emotion/styled", "framer-motion"], + "vendor-i18n": ["i18next", "react-i18next"], + "vendor-icons": ["react-icons", "react-social-icons"], + "vendor-swiper": ["swiper"], + "vendor-markdown": ["react-markdown"], + } + } + } } }) \ No newline at end of file