import React, { lazy, Suspense, ComponentType, ReactNode } from 'react'; import { Skeleton, Spin } from '@/shared/antd-imports'; // Enhanced lazy loading with error boundary and retry logic export function createOptimizedLazy>( importFunc: () => Promise<{ default: T }>, fallback?: ReactNode ): React.LazyExoticComponent { let retryCount = 0; const maxRetries = 3; const retryImport = async (): Promise<{ default: T }> => { try { return await importFunc(); } catch (error) { if (retryCount < maxRetries) { retryCount++; console.warn(`Lazy loading failed, retrying... (${retryCount}/${maxRetries})`); // Exponential backoff: 500ms, 1s, 2s await new Promise(resolve => setTimeout(resolve, 500 * Math.pow(2, retryCount - 1))); return retryImport(); } throw error; } }; return lazy(retryImport); } // Preloading utility for components that will likely be used export const preloadComponent = >( importFunc: () => Promise<{ default: T }> ): void => { // Preload on user interaction or after a delay if ('requestIdleCallback' in window) { (window as any).requestIdleCallback(() => { importFunc().catch(() => { // Ignore preload errors }); }); } else { setTimeout(() => { importFunc().catch(() => { // Ignore preload errors }); }, 2000); } }; // Lazy-loaded task management components with optimized fallbacks export const LazyTaskListBoard = createOptimizedLazy( () => import('./task-list-board'),
); export const LazyVirtualizedTaskList = createOptimizedLazy( () => import('./virtualized-task-list'), ); export const LazyTaskRow = createOptimizedLazy( () => import('./task-row'), ); export const LazyImprovedTaskFilters = createOptimizedLazy( () => import('./improved-task-filters'), ); export const LazyOptimizedBulkActionBar = createOptimizedLazy( () => import('./optimized-bulk-action-bar'), ); export const LazyPerformanceAnalysis = createOptimizedLazy( () => import('./performance-analysis'),
Loading performance tools...
); // Kanban-specific components export const LazyKanbanTaskListBoard = createOptimizedLazy( () => import('../kanban-board-management-v2/kanbanTaskListBoard'),
); // Task list V2 components export const LazyTaskListV2Table = createOptimizedLazy( () => import('../task-list-v2/TaskListV2Table'), ); export const LazyTaskRowWithSubtasks = createOptimizedLazy( () => import('../task-list-v2/TaskRowWithSubtasks'), ); export const LazyCustomColumnModal = createOptimizedLazy( () => import('@/pages/projects/projectView/taskList/task-list-table/custom-columns/custom-column-modal/custom-column-modal'),
); export const LazyLabelsSelector = createOptimizedLazy( () => import('@/components/LabelsSelector'), ); export const LazyAssigneeSelector = createOptimizedLazy( () => import('./lazy-assignee-selector'), ); export const LazyTaskStatusDropdown = createOptimizedLazy( () => import('./task-status-dropdown'), ); export const LazyTaskPriorityDropdown = createOptimizedLazy( () => import('./task-priority-dropdown'), ); export const LazyTaskPhaseDropdown = createOptimizedLazy( () => import('./task-phase-dropdown'), ); // HOC for progressive enhancement interface ProgressiveEnhancementProps { condition: boolean; children: ReactNode; fallback?: ReactNode; loadingComponent?: ReactNode; } export const ProgressiveEnhancement: React.FC = ({ condition, children, fallback, loadingComponent = }) => { if (!condition) { return <>{fallback || loadingComponent}; } return ( {children} ); }; // Intersection observer based lazy loading for components interface IntersectionLazyLoadProps { children: ReactNode; fallback?: ReactNode; rootMargin?: string; threshold?: number; once?: boolean; } export const IntersectionLazyLoad: React.FC = ({ children, fallback = , rootMargin = '100px', threshold = 0.1, once = true }) => { const [isVisible, setIsVisible] = React.useState(false); const [hasBeenVisible, setHasBeenVisible] = React.useState(false); const ref = React.useRef(null); React.useEffect(() => { const element = ref.current; if (!element) return; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsVisible(true); if (once) { setHasBeenVisible(true); observer.disconnect(); } } else if (!once) { setIsVisible(false); } }, { rootMargin, threshold } ); observer.observe(element); return () => { observer.disconnect(); }; }, [rootMargin, threshold, once]); const shouldRender = isVisible || hasBeenVisible; return (
{shouldRender ? ( {children} ) : ( fallback )}
); }; // Route-based code splitting utility export const createRouteComponent = >( importFunc: () => Promise<{ default: T }>, pageTitle?: string ) => { const LazyComponent = createOptimizedLazy(importFunc); return React.memo(() => { React.useEffect(() => { if (pageTitle) { document.title = pageTitle; } }, []); return ( } > ); }); }; // Bundle splitting by feature export const TaskManagementBundle = { TaskListBoard: LazyTaskListBoard, VirtualizedTaskList: LazyVirtualizedTaskList, TaskRow: LazyTaskRow, TaskFilters: LazyImprovedTaskFilters, BulkActionBar: LazyOptimizedBulkActionBar, PerformanceAnalysis: LazyPerformanceAnalysis, }; export const KanbanBundle = { KanbanBoard: LazyKanbanTaskListBoard, }; export const TaskListV2Bundle = { TaskTable: LazyTaskListV2Table, TaskRowWithSubtasks: LazyTaskRowWithSubtasks, }; export const FormBundle = { CustomColumnModal: LazyCustomColumnModal, LabelsSelector: LazyLabelsSelector, AssigneeSelector: LazyAssigneeSelector, }; export const DropdownBundle = { StatusDropdown: LazyTaskStatusDropdown, PriorityDropdown: LazyTaskPriorityDropdown, PhaseDropdown: LazyTaskPhaseDropdown, }; // Preloading strategies export const preloadTaskManagementComponents = () => { // Preload core components that are likely to be used preloadComponent(() => import('./task-list-board')); preloadComponent(() => import('./virtualized-task-list')); preloadComponent(() => import('./improved-task-filters')); }; export const preloadKanbanComponents = () => { preloadComponent(() => import('../kanban-board-management-v2/kanbanTaskListBoard')); }; export const preloadFormComponents = () => { preloadComponent(() => import('@/components/LabelsSelector')); }; // Dynamic import utilities export const importTaskComponent = async (componentName: string) => { const componentMap: Record Promise> = { 'task-list-board': () => import('./task-list-board'), 'virtualized-task-list': () => import('./virtualized-task-list'), 'task-row': () => import('./task-row'), 'improved-task-filters': () => import('./improved-task-filters'), 'optimized-bulk-action-bar': () => import('./optimized-bulk-action-bar'), 'performance-analysis': () => import('./performance-analysis'), }; const importFunc = componentMap[componentName]; if (!importFunc) { throw new Error(`Component ${componentName} not found`); } return importFunc(); }; // Error boundary for lazy loaded components interface LazyErrorBoundaryState { hasError: boolean; error?: Error; } export class LazyErrorBoundary extends React.Component< { children: ReactNode; fallback?: ReactNode }, LazyErrorBoundaryState > { constructor(props: { children: ReactNode; fallback?: ReactNode }) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error): LazyErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error('Lazy loading error:', error, errorInfo); } render() { if (this.state.hasError) { return ( this.props.fallback || (

Failed to load component

) ); } return this.props.children; } } // Usage example and documentation export const LazyLoadingExamples = { // Basic lazy loading with suspense BasicExample: () => ( }> ), // Progressive enhancement ProgressiveExample: () => ( {}} onToggleSubtasks={() => {}} /> ), // Intersection observer lazy loading IntersectionExample: () => ( ), // Error boundary with lazy loading ErrorBoundaryExample: () => ( }> {}} onToggleSubtasks={() => {}} /> ), };