feat(performance): implement comprehensive performance improvements for Worklenz frontend
- Introduced a new document summarizing performance optimizations across the application. - Applied React.memo(), useMemo(), and useCallback() to key components to minimize unnecessary re-renders and optimize rendering performance. - Implemented a route preloading system to enhance navigation speed and user experience. - Added performance monitoring utilities for development to track component render times and function execution. - Enhanced lazy loading and suspense boundaries for better loading states. - Conducted production optimizations, including TypeScript error fixes and memory management improvements. - Memoized style and configuration objects to reduce garbage collection pressure and improve memory usage.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Core dependencies
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import React, { Suspense, useEffect, memo, useMemo, useCallback } from 'react';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
import i18next from 'i18next';
|
||||
|
||||
@@ -14,33 +14,82 @@ import router from './app/routes';
|
||||
import { useAppSelector } from './hooks/useAppSelector';
|
||||
import { initMixpanel } from './utils/mixpanelInit';
|
||||
import { initializeCsrfToken } from './api/api-client';
|
||||
import { useRoutePreloader } from './utils/routePreloader';
|
||||
|
||||
// Types & Constants
|
||||
import { Language } from './features/i18n/localesSlice';
|
||||
import logger from './utils/errorLogger';
|
||||
import { SuspenseFallback } from './components/suspense-fallback/suspense-fallback';
|
||||
|
||||
const App: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
/**
|
||||
* Main App Component - Performance Optimized
|
||||
*
|
||||
* Performance optimizations applied:
|
||||
* 1. React.memo() - Prevents unnecessary re-renders
|
||||
* 2. useMemo() - Memoizes expensive computations
|
||||
* 3. useCallback() - Memoizes event handlers
|
||||
* 4. Route preloading - Preloads critical routes
|
||||
* 5. Lazy loading - Components loaded on demand
|
||||
* 6. Suspense boundaries - Better loading states
|
||||
*/
|
||||
const App: React.FC = memo(() => {
|
||||
const themeMode = useAppSelector(state => state.themeReducer.mode);
|
||||
const language = useAppSelector(state => state.localesReducer.lng);
|
||||
|
||||
initMixpanel(import.meta.env.VITE_MIXPANEL_TOKEN as string);
|
||||
// Memoize mixpanel initialization to prevent re-initialization
|
||||
const mixpanelToken = useMemo(() => import.meta.env.VITE_MIXPANEL_TOKEN as string, []);
|
||||
|
||||
// Preload critical routes for better navigation performance
|
||||
useRoutePreloader([
|
||||
{
|
||||
path: '/worklenz/home',
|
||||
loader: () => import('./pages/home/home-page'),
|
||||
priority: 'high'
|
||||
},
|
||||
{
|
||||
path: '/worklenz/projects',
|
||||
loader: () => import('./pages/projects/project-list'),
|
||||
priority: 'high'
|
||||
},
|
||||
{
|
||||
path: '/worklenz/schedule',
|
||||
loader: () => import('./pages/schedule/schedule'),
|
||||
priority: 'medium'
|
||||
}
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
initMixpanel(mixpanelToken);
|
||||
}, [mixpanelToken]);
|
||||
|
||||
// Memoize language change handler
|
||||
const handleLanguageChange = useCallback((lng: string) => {
|
||||
i18next.changeLanguage(lng, err => {
|
||||
if (err) return logger.error('Error changing language', err);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.setAttribute('data-theme', themeMode);
|
||||
}, [themeMode]);
|
||||
|
||||
useEffect(() => {
|
||||
i18next.changeLanguage(language || Language.EN, err => {
|
||||
if (err) return logger.error('Error changing language', err);
|
||||
});
|
||||
}, [language]);
|
||||
handleLanguageChange(language || Language.EN);
|
||||
}, [language, handleLanguageChange]);
|
||||
|
||||
// Initialize CSRF token on app startup
|
||||
// Initialize CSRF token on app startup - memoize to prevent re-initialization
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
initializeCsrfToken().catch(error => {
|
||||
logger.error('Failed to initialize CSRF token:', error);
|
||||
if (isMounted) {
|
||||
logger.error('Failed to initialize CSRF token:', error);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -50,6 +99,8 @@ const App: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
</ThemeWrapper>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
App.displayName = 'App';
|
||||
|
||||
export default App;
|
||||
|
||||
Reference in New Issue
Block a user