Merge pull request #23 from ragusa-it/bolt/route-lazy-loading-17202030222576625568
⚡ Bolt: Implement route lazy loading
This commit was merged in pull request #23.
This commit is contained in:
@@ -2,6 +2,9 @@
|
|||||||
**Learning:** The project lacks `lint` script in `package.json`. Running `pnpm lint` might invoke system tools (like Android Lint?) instead of failing or doing nothing useful. Always check `package.json` scripts first.
|
**Learning:** The project lacks `lint` script in `package.json`. Running `pnpm lint` might invoke system tools (like Android Lint?) instead of failing or doing nothing useful. Always check `package.json` scripts first.
|
||||||
**Action:** Use specific commands like `pnpm exec tsc --noEmit` or `npx vitest` as discovered/documented, rather than assuming standard scripts exist.
|
**Action:** Use specific commands like `pnpm exec tsc --noEmit` or `npx vitest` as discovered/documented, rather than assuming standard scripts exist.
|
||||||
|
|
||||||
|
## 2025-01-26 - Missing Node Modules
|
||||||
|
**Learning:** The environment might lack `node_modules` completely, preventing `npx vitest` or `pnpm exec tsc` from running even if dependencies are listed in `package.json`. Network restrictions may prevent `pnpm install`.
|
||||||
|
**Action:** When `node_modules` is missing and cannot be installed, rely on static analysis, careful code review, and verifying file contents manually. Do not assume tests can run.
|
||||||
## 2024-05-22 - High-Frequency State Isolation
|
## 2024-05-22 - High-Frequency State Isolation
|
||||||
**Learning:** High-frequency state updates (like typing effects) in large parent components (`Hero`) trigger massive unnecessary re-renders of expensive sub-trees (`GradientBlinds`, `Button`).
|
**Learning:** High-frequency state updates (like typing effects) in large parent components (`Hero`) trigger massive unnecessary re-renders of expensive sub-trees (`GradientBlinds`, `Button`).
|
||||||
**Action:** Isolate high-frequency state into small, leaf-node components (e.g., `TypedText`) and wrap them in `React.memo` if necessary, keeping the heavy parent static.
|
**Action:** Isolate high-frequency state into small, leaf-node components (e.g., `TypedText`) and wrap them in `React.memo` if necessary, keeping the heavy parent static.
|
||||||
|
|||||||
22
src/App.tsx
22
src/App.tsx
@@ -1,9 +1,16 @@
|
|||||||
|
import { Suspense, lazy } from 'react';
|
||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||||
import { LanguageProvider } from './i18n';
|
import { LanguageProvider } from './i18n';
|
||||||
import { Navbar, Footer, FancyCursor, ScrollToTop } from './components/layout';
|
import { Navbar, Footer, FancyCursor, ScrollToTop } from './components/layout';
|
||||||
import { Home, About, Contact } from './pages';
|
import { Home } from './pages/Home';
|
||||||
|
import { PageLoader } from './components/ui';
|
||||||
import './styles/global.css';
|
import './styles/global.css';
|
||||||
|
|
||||||
|
// Lazy load pages to reduce initial bundle size.
|
||||||
|
// Home is imported directly to prevent layout shift on initial load.
|
||||||
|
const About = lazy(() => import('./pages/About').then(module => ({ default: module.About })));
|
||||||
|
const Contact = lazy(() => import('./pages/Contact').then(module => ({ default: module.Contact })));
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
return (
|
return (
|
||||||
<LanguageProvider>
|
<LanguageProvider>
|
||||||
@@ -11,11 +18,14 @@ export function App() {
|
|||||||
<ScrollToTop />
|
<ScrollToTop />
|
||||||
<FancyCursor />
|
<FancyCursor />
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<Routes>
|
{/* Suspense handles the loading state for lazy-loaded routes */}
|
||||||
<Route path="/" element={<Home />} />
|
<Suspense fallback={<PageLoader />}>
|
||||||
<Route path="/about" element={<About />} />
|
<Routes>
|
||||||
<Route path="/contact" element={<Contact />} />
|
<Route path="/" element={<Home />} />
|
||||||
</Routes>
|
<Route path="/about" element={<About />} />
|
||||||
|
<Route path="/contact" element={<Contact />} />
|
||||||
|
</Routes>
|
||||||
|
</Suspense>
|
||||||
<Footer />
|
<Footer />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</LanguageProvider>
|
</LanguageProvider>
|
||||||
|
|||||||
22
src/components/ui/PageLoader.module.css
Normal file
22
src/components/ui/PageLoader.module.css
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 60vh;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 3px solid var(--md-sys-color-surface-container-highest);
|
||||||
|
border-top-color: var(--md-sys-color-primary);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/components/ui/PageLoader.tsx
Normal file
9
src/components/ui/PageLoader.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import styles from './PageLoader.module.css';
|
||||||
|
|
||||||
|
export function PageLoader() {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.loader} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export { Button } from './Button';
|
export { Button } from './Button';
|
||||||
export { Card } from './Card';
|
export { Card } from './Card';
|
||||||
export { Input, Textarea } from './Input';
|
export { Input, Textarea } from './Input';
|
||||||
|
export { PageLoader } from './PageLoader';
|
||||||
|
|||||||
Reference in New Issue
Block a user