|
import React, { lazy, Suspense } from 'react'; |
|
import { memoize } from './PerformanceOptimizer'; |
|
import { intelligentPreloader, resourceHints } from './BundleOptimizer'; |
|
|
|
|
|
const createOptimizedLazyComponent = (importFn: () => Promise<{ default: React.ComponentType<any> }>, key: string) => { |
|
const LazyComponent = lazy(importFn); |
|
|
|
|
|
intelligentPreloader.register(key, importFn); |
|
|
|
|
|
(LazyComponent as any).preload = importFn; |
|
|
|
return LazyComponent; |
|
}; |
|
|
|
|
|
export const DualGameViewer = createOptimizedLazyComponent(() => import('../components/DualGameViewer'), 'DualGameViewer'); |
|
export const Statistics = createOptimizedLazyComponent(() => import('../components/Statistics'), 'Statistics'); |
|
export const ResultsAnalysis = createOptimizedLazyComponent(() => import('../components/ResultsAnalysis'), 'ResultsAnalysis'); |
|
export const ProbabilityCalculator = createOptimizedLazyComponent(() => import('../components/ProbabilityCalculator'), 'ProbabilityCalculator'); |
|
export const EnhancedLotomaniaGrid = createOptimizedLazyComponent(() => import('../components/EnhancedLotomaniaGrid'), 'EnhancedLotomaniaGrid'); |
|
export const LotomaniaFeatures = createOptimizedLazyComponent(() => import('../components/LotomaniaFeatures'), 'LotomaniaFeatures'); |
|
export const PrizeAnalysis = createOptimizedLazyComponent(() => import('../components/PrizeAnalysis'), 'PrizeAnalysis'); |
|
export const GameProfitabilityAnalysis = createOptimizedLazyComponent(() => import('../components/GameProfitabilityAnalysis'), 'GameProfitabilityAnalysis'); |
|
export const HistoricalTrends = createOptimizedLazyComponent(() => import('../components/HistoricalTrends'), 'HistoricalTrends'); |
|
export const SmartNumberGenerator = createOptimizedLazyComponent(() => import('../components/SmartNumberGenerator'), 'SmartNumberGenerator'); |
|
|
|
|
|
interface ComponentLoaderProps { |
|
message?: string; |
|
size?: 'sm' | 'md' | 'lg'; |
|
} |
|
|
|
export const ComponentLoader: React.FC<ComponentLoaderProps> = React.memo(({ |
|
message = 'Carregando...', |
|
size = 'md' |
|
}) => { |
|
const sizeClasses = { |
|
sm: 'h-6 w-6', |
|
md: 'h-12 w-12', |
|
lg: 'h-16 w-16' |
|
}; |
|
|
|
return ( |
|
<div className="flex items-center justify-center p-8"> |
|
<div className="flex flex-col items-center space-y-4"> |
|
<div className={`animate-spin rounded-full border-b-2 border-blue-600 ${sizeClasses[size]}`}></div> |
|
<p className="text-gray-600 font-medium">{message}</p> |
|
</div> |
|
</div> |
|
); |
|
}); |
|
|
|
ComponentLoader.displayName = 'ComponentLoader'; |
|
|
|
|
|
export function withLoadingFallback<P extends object>( |
|
WrappedComponent: React.ComponentType<P>, |
|
loadingMessage?: string |
|
): React.FC<P> { |
|
const WrappedWithSuspense: React.FC<P> = (props: P) => { |
|
return ( |
|
<Suspense fallback={<ComponentLoader message={loadingMessage} />}> |
|
<WrappedComponent {...props} /> |
|
</Suspense> |
|
); |
|
}; |
|
|
|
WrappedWithSuspense.displayName = `withLoadingFallback(${WrappedComponent.displayName || WrappedComponent.name})`; |
|
|
|
return WrappedWithSuspense; |
|
} |
|
|
|
|
|
export const preloadCriticalComponents = memoize(async (): Promise<void> => { |
|
try { |
|
|
|
resourceHints.setupApiHints(); |
|
|
|
|
|
await intelligentPreloader.preloadByPriority([ |
|
'DualGameViewer', |
|
'EnhancedLotomaniaGrid', |
|
'Statistics' |
|
]); |
|
|
|
console.log('✅ Componentes críticos pré-carregados'); |
|
} catch (error) { |
|
console.warn('❌ Falha ao precarregar componentes:', error); |
|
} |
|
}); |
|
|
|
|
|
export const conditionalPreload = (): void => { |
|
|
|
const shouldPreload = checkPreloadConditions(); |
|
|
|
if (shouldPreload) { |
|
|
|
if ('requestIdleCallback' in window) { |
|
(window as any).requestIdleCallback( |
|
() => preloadCriticalComponents(), |
|
{ timeout: 3000 } |
|
); |
|
} else { |
|
setTimeout(() => preloadCriticalComponents(), 1000); |
|
} |
|
} |
|
}; |
|
|
|
|
|
function checkPreloadConditions(): boolean { |
|
|
|
if ('connection' in navigator) { |
|
const connection = (navigator as any).connection; |
|
if (connection) { |
|
|
|
if (connection.saveData || connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g') { |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
|
|
if ('memory' in performance) { |
|
const memory = (performance as any).memory; |
|
if (memory && memory.usedJSHeapSize / memory.jsHeapSizeLimit > 0.8) { |
|
return false; |
|
} |
|
} |
|
|
|
|
|
if (navigator.hardwareConcurrency && navigator.hardwareConcurrency < 4) { |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|