mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-26 22:54:54 +00:00
182 lines
5.4 KiB
TypeScript
182 lines
5.4 KiB
TypeScript
import { getEnabledPages } from '@/config/page-loader'
|
|
import { preloadComponentByName, ComponentName } from '@/lib/component-registry'
|
|
import { FeatureToggles } from '@/types/project'
|
|
import { preloadLibrary } from '@/lib/library-loader'
|
|
|
|
interface PreloadStrategy {
|
|
preloadAdjacent: boolean
|
|
preloadPopular: boolean
|
|
maxConcurrentPreloads: number
|
|
}
|
|
|
|
const DEFAULT_STRATEGY: PreloadStrategy = {
|
|
preloadAdjacent: true,
|
|
preloadPopular: true,
|
|
maxConcurrentPreloads: 3,
|
|
}
|
|
|
|
const popularRoutes = new Set(['dashboard', 'editor', 'models', 'components'])
|
|
|
|
const preloadQueue: Array<() => void> = []
|
|
let activePreloads = 0
|
|
|
|
function processPreloadQueue(strategy: PreloadStrategy) {
|
|
while (activePreloads < strategy.maxConcurrentPreloads && preloadQueue.length > 0) {
|
|
const preload = preloadQueue.shift()
|
|
if (preload) {
|
|
activePreloads++
|
|
preload()
|
|
setTimeout(() => {
|
|
activePreloads--
|
|
processPreloadQueue(strategy)
|
|
}, 100)
|
|
}
|
|
}
|
|
}
|
|
|
|
export class RoutePreloadManager {
|
|
private strategy: PreloadStrategy
|
|
private preloadedRoutes = new Set<string>()
|
|
private currentRoute: string | null = null
|
|
private featureToggles: FeatureToggles | null = null
|
|
|
|
constructor(strategy: Partial<PreloadStrategy> = {}) {
|
|
this.strategy = { ...DEFAULT_STRATEGY, ...strategy }
|
|
console.log('[PRELOAD_MGR] 🎯 RoutePreloadManager initialized with strategy:', this.strategy)
|
|
}
|
|
|
|
setFeatureToggles(featureToggles: FeatureToggles) {
|
|
this.featureToggles = featureToggles
|
|
console.log('[PRELOAD_MGR] ⚙️ Feature toggles set')
|
|
}
|
|
|
|
setCurrentRoute(route: string) {
|
|
console.log(`[PRELOAD_MGR] 📍 Current route changed: ${this.currentRoute} → ${route}`)
|
|
this.currentRoute = route
|
|
|
|
if (this.strategy.preloadAdjacent) {
|
|
this.preloadAdjacentRoutes(route)
|
|
}
|
|
}
|
|
|
|
preloadRoute(pageId: string, priority: 'high' | 'low' = 'low') {
|
|
if (this.preloadedRoutes.has(pageId)) {
|
|
console.log(`[PRELOAD_MGR] ✅ Route ${pageId} already preloaded`)
|
|
return
|
|
}
|
|
|
|
console.log(`[PRELOAD_MGR] 🎯 Queuing preload for route: ${pageId} (priority: ${priority})`)
|
|
|
|
const preloadFn = () => {
|
|
if (this.preloadedRoutes.has(pageId)) return
|
|
|
|
const pages = getEnabledPages(this.featureToggles || undefined)
|
|
const page = pages.find(p => p.id === pageId)
|
|
|
|
if (!page) {
|
|
console.warn(`[PRELOAD_MGR] ⚠️ Page not found: ${pageId}`)
|
|
return
|
|
}
|
|
|
|
try {
|
|
const componentName = page.component as ComponentName
|
|
console.log(`[PRELOAD_MGR] 🚀 Preloading ${pageId} → ${componentName}`)
|
|
preloadComponentByName(componentName)
|
|
|
|
if (page.requiresResizable && page.resizableConfig) {
|
|
const leftComponentName = page.resizableConfig.leftComponent as ComponentName
|
|
console.log(`[PRELOAD_MGR] 🚀 Preloading left panel: ${leftComponentName}`)
|
|
preloadComponentByName(leftComponentName)
|
|
}
|
|
|
|
this.preloadedRoutes.add(pageId)
|
|
console.log(`[PRELOAD_MGR] ✅ Route ${pageId} preloaded`)
|
|
} catch (error) {
|
|
console.error(`[PRELOAD_MGR] ❌ Failed to preload ${pageId}:`, error)
|
|
}
|
|
}
|
|
|
|
if (priority === 'high') {
|
|
preloadQueue.unshift(preloadFn)
|
|
} else {
|
|
preloadQueue.push(preloadFn)
|
|
}
|
|
|
|
processPreloadQueue(this.strategy)
|
|
}
|
|
|
|
preloadAdjacentRoutes(currentRoute: string) {
|
|
if (!this.featureToggles) {
|
|
console.warn('[PRELOAD_MGR] ⚠️ Cannot preload adjacent routes: feature toggles not set')
|
|
return
|
|
}
|
|
|
|
const pages = getEnabledPages(this.featureToggles)
|
|
const currentIndex = pages.findIndex(p => p.id === currentRoute)
|
|
|
|
if (currentIndex === -1) {
|
|
console.warn(`[PRELOAD_MGR] ⚠️ Current route not found in enabled pages: ${currentRoute}`)
|
|
return
|
|
}
|
|
|
|
console.log(`[PRELOAD_MGR] 🔄 Preloading adjacent routes to ${currentRoute}`)
|
|
|
|
if (currentIndex > 0) {
|
|
const prevPage = pages[currentIndex - 1]
|
|
console.log(`[PRELOAD_MGR] ← Preloading previous route: ${prevPage.id}`)
|
|
this.preloadRoute(prevPage.id, 'low')
|
|
}
|
|
|
|
if (currentIndex < pages.length - 1) {
|
|
const nextPage = pages[currentIndex + 1]
|
|
console.log(`[PRELOAD_MGR] → Preloading next route: ${nextPage.id}`)
|
|
this.preloadRoute(nextPage.id, 'low')
|
|
}
|
|
}
|
|
|
|
preloadPopularRoutes() {
|
|
if (!this.strategy.preloadPopular) {
|
|
console.log('[PRELOAD_MGR] ⏭️ Popular route preloading disabled')
|
|
return
|
|
}
|
|
|
|
console.log('[PRELOAD_MGR] ⭐ Preloading popular routes')
|
|
|
|
popularRoutes.forEach(route => {
|
|
if (!this.preloadedRoutes.has(route)) {
|
|
this.preloadRoute(route, 'low')
|
|
}
|
|
})
|
|
}
|
|
|
|
preloadLibraries(libraries: Array<'recharts' | 'd3' | 'three' | 'reactflow'>) {
|
|
console.log('[PRELOAD_MGR] 📚 Preloading libraries:', libraries)
|
|
libraries.forEach(lib => {
|
|
preloadLibrary(lib)
|
|
})
|
|
}
|
|
|
|
isPreloaded(pageId: string): boolean {
|
|
return this.preloadedRoutes.has(pageId)
|
|
}
|
|
|
|
reset() {
|
|
console.log('[PRELOAD_MGR] 🔄 Resetting preload manager')
|
|
this.preloadedRoutes.clear()
|
|
this.currentRoute = null
|
|
preloadQueue.length = 0
|
|
activePreloads = 0
|
|
}
|
|
|
|
getStats() {
|
|
return {
|
|
preloadedCount: this.preloadedRoutes.size,
|
|
queuedCount: preloadQueue.length,
|
|
activePreloads,
|
|
currentRoute: this.currentRoute,
|
|
}
|
|
}
|
|
}
|
|
|
|
export const routePreloadManager = new RoutePreloadManager()
|