Skip to content

Commit 26400c3

Browse files
feat: implement lazy loading for various components and improve socket connection handling
1 parent a137a69 commit 26400c3

8 files changed

Lines changed: 220 additions & 148 deletions

File tree

apps/client/netlify.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[build]
2+
command = "pnpm build"
3+
publish = "dist"
4+
5+
[[redirects]]
6+
from = "/*"
7+
to = "/index.html"
8+
status = 200
9+
10+
[[headers]]
11+
for = "/assets/*"
12+
[headers.values]
13+
Cache-Control = "public, max-age=31536000, immutable"
14+
15+
[[headers]]
16+
for = "/*.html"
17+
[headers.values]
18+
Cache-Control = "public, max-age=0, must-revalidate"

apps/client/src/App.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import { UserProvider } from "./contexts/UserContext";
77
import { GradientProvider } from "./contexts/GradientContext";
88
import "./App.css";
99
import { Toaster } from "./components/shadcn/ui/toaster";
10-
import ResetPasswordPage from "./pages/ResetPasswordPage";
11-
import EmailVerificationPage from "./pages/EmailVerificationPage";
1210
import { SocketProvider } from "./contexts/SocketContext";
1311
import { Provider as JotaiProvider } from "jotai";
1412

1513
const HomePage = React.lazy(() => import("./pages/HomePage")); // Lazy load the HomePage
14+
const EmailVerificationPage = React.lazy(
15+
() => import("./pages/EmailVerificationPage")
16+
);
17+
const ResetPasswordPage = React.lazy(() => import("./pages/ResetPasswordPage"));
1618

1719
function App() {
1820
return (

apps/client/src/components/NavBar.tsx

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Link, useNavigate } from "react-router-dom";
2-
import React, { useState, useContext, useEffect } from "react";
2+
import React, { useState, useContext, useEffect, Suspense } from "react";
33
import { logout } from "../services/MindsMeshAPI";
44
import { Button } from "./shadcn/ui/button";
55
import {
@@ -16,13 +16,15 @@ import {
1616
Pencil1Icon,
1717
} from "@radix-ui/react-icons";
1818
import { FaPalette } from "react-icons/fa";
19-
import LoginForm from "./LoginForm";
20-
import RegisterForm from "./RegisterForm";
21-
import EditProfileForm from "./EditProfileForm";
2219
import logo from "../assets/logo.svg";
2320
import { UserContext } from "../contexts/UserContext";
2421
import { useGradient } from "../hooks/useGradient";
2522
import { useToast } from "./shadcn/ui/use-toast";
23+
import LoadingSpinner from "../helpers/LoadingSpinner";
24+
25+
const LoginForm = React.lazy(() => import("./LoginForm"));
26+
const RegisterForm = React.lazy(() => import("./RegisterForm"));
27+
const EditProfileForm = React.lazy(() => import("./EditProfileForm"));
2628

2729
const Navbar: React.FC = () => {
2830
const navigate = useNavigate();
@@ -75,7 +77,9 @@ const Navbar: React.FC = () => {
7577
}, [menuOpen]);
7678

7779
return (
78-
<nav className={`navbar p-2 h-16 top-0 z-50 transition-colors duration-500`}>
80+
<nav
81+
className={`navbar p-2 h-16 top-0 z-50 transition-colors duration-500`}
82+
>
7983
<div className="container mx-auto flex justify-between items-center">
8084
{/* Logo and Brand Name */}
8185
<Link
@@ -141,7 +145,9 @@ const Navbar: React.FC = () => {
141145
<DialogHeader>
142146
<DialogTitle>Login</DialogTitle>
143147
</DialogHeader>
144-
<LoginForm />
148+
<Suspense fallback={<LoadingSpinner />}>
149+
<LoginForm />
150+
</Suspense>
145151
</DialogContent>
146152
</Dialog>
147153

@@ -162,9 +168,11 @@ const Navbar: React.FC = () => {
162168
<DialogHeader>
163169
<DialogTitle>Register</DialogTitle>
164170
</DialogHeader>
165-
<RegisterForm
166-
onClose={() => setIsRegisterDialogOpen(false)}
167-
/>
171+
<Suspense fallback={<LoadingSpinner />}>
172+
<RegisterForm
173+
onClose={() => setIsRegisterDialogOpen(false)}
174+
/>
175+
</Suspense>
168176
</DialogContent>
169177
</Dialog>
170178
</>
@@ -255,7 +263,9 @@ const Navbar: React.FC = () => {
255263
<DialogHeader>
256264
<DialogTitle>Login</DialogTitle>
257265
</DialogHeader>
258-
<LoginForm />
266+
<Suspense fallback={<LoadingSpinner />}>
267+
<LoginForm />
268+
</Suspense>
259269
</DialogContent>
260270
</Dialog>
261271

@@ -280,7 +290,11 @@ const Navbar: React.FC = () => {
280290
<DialogHeader>
281291
<DialogTitle>Register</DialogTitle>
282292
</DialogHeader>
283-
<RegisterForm onClose={() => setIsRegisterDialogOpen(false)} />
293+
<Suspense fallback={<LoadingSpinner />}>
294+
<RegisterForm
295+
onClose={() => setIsRegisterDialogOpen(false)}
296+
/>
297+
</Suspense>
284298
</DialogContent>
285299
</Dialog>
286300
</>
@@ -293,16 +307,18 @@ const Navbar: React.FC = () => {
293307
<DialogHeader>
294308
<DialogTitle>Edit Profile</DialogTitle>
295309
</DialogHeader>
296-
{user && (
297-
<EditProfileForm
298-
user={user}
299-
setUser={(updatedUser) => {
300-
setUser(updatedUser);
301-
setIsProfileOpen(false);
302-
refreshUser();
303-
}}
304-
/>
305-
)}
310+
<Suspense fallback={<LoadingSpinner />}>
311+
{user && (
312+
<EditProfileForm
313+
user={user}
314+
setUser={(updatedUser) => {
315+
setUser(updatedUser);
316+
setIsProfileOpen(false);
317+
refreshUser();
318+
}}
319+
/>
320+
)}
321+
</Suspense>
306322
</DialogContent>
307323
</Dialog>
308324
</nav>

apps/client/src/contexts/SocketContext.tsx

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,64 @@
11
// src/contexts/SocketContext.tsx
22

3-
import React, { createContext, useEffect, useState, ReactNode } from 'react';
4-
import { io, Socket } from 'socket.io-client';
5-
import { useUserContext } from '../hooks/useUserContext'; // Import the custom hook
3+
import React, { createContext, useEffect, useState, ReactNode } from "react";
4+
import type { Socket } from "socket.io-client";
5+
import { useUserContext } from "../hooks/useUserContext"; // Import the custom hook
66

77
interface SocketContextProps {
88
socket: Socket | null;
99
}
1010

11-
export const SocketContext = createContext<SocketContextProps>({ socket: null });
11+
export const SocketContext = createContext<SocketContextProps>({
12+
socket: null,
13+
});
1214

13-
export const SocketProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
15+
export const SocketProvider: React.FC<{ children: ReactNode }> = ({
16+
children,
17+
}) => {
1418
const [socket, setSocket] = useState<Socket | null>(null);
1519
const backendUrl = import.meta.env.VITE_BASE_URL_CHAT_EMPLOYER; // Adjust as needed
1620
const { user } = useUserContext(); // Use the custom hook to get user
1721

1822
useEffect(() => {
19-
// Retrieve the token from localStorage
20-
const token = localStorage.getItem('token');
23+
let isActive = true;
24+
let newSocket: Socket | null = null;
2125

22-
if (token) {
23-
const newSocket = io(backendUrl, {
26+
const connect = async () => {
27+
const token = localStorage.getItem("token");
28+
if (!token || !backendUrl) {
29+
setSocket(null);
30+
return;
31+
}
32+
33+
const { io } = await import("socket.io-client");
34+
if (!isActive) return;
35+
36+
newSocket = io(backendUrl, {
2437
auth: { token },
2538
});
26-
2739
setSocket(newSocket);
2840

29-
newSocket.on('connect', () => {
30-
console.log('Socket connected');
41+
newSocket.on("connect", () => {
42+
console.log("Socket connected");
3143
});
3244

33-
newSocket.on('disconnect', () => {
34-
console.log('Socket disconnected');
45+
newSocket.on("disconnect", () => {
46+
console.log("Socket disconnected");
3547
});
3648

37-
newSocket.on('connect_error', (err) => {
38-
console.error('Socket connection error:', err);
49+
newSocket.on("connect_error", (err) => {
50+
console.error("Socket connection error:", err);
3951
});
52+
};
53+
54+
connect();
4055

41-
return () => {
56+
return () => {
57+
isActive = false;
58+
if (newSocket) {
4259
newSocket.disconnect();
43-
};
44-
}
60+
}
61+
};
4562
}, [backendUrl, user]);
4663

4764
return (

0 commit comments

Comments
 (0)