7.4 KiB
Hover-Based Route Preloading
Overview
The application now implements intelligent hover-based preloading for instant page navigation. When users hover over navigation items, the route components are preloaded in the background, making subsequent navigation feel instantaneous.
Architecture
Components
-
useRoutePreloadHook (/src/hooks/use-route-preload.ts)- React hook for triggering route preloading
- Manages preload cache and timers
- Provides
preloadRoute,cancelPreload, and status checking functions - Configurable delay (default: 100ms) before preload starts
-
RoutePreloadManagerClass (/src/lib/route-preload-manager.ts)- Singleton manager for intelligent preloading strategies
- Implements queue-based preloading with concurrency control
- Supports multiple preload strategies:
- Adjacent Routes: Preloads previous/next routes in the navigation order
- Popular Routes: Preloads frequently accessed routes (dashboard, editor, models, components)
- Tracks preload stats and provides insights
-
lazyWithPreloadUtility (/src/lib/lazy-loader.ts)- Enhanced lazy loading wrapper with preload support
- All components in
ComponentRegistrynow support.preload()method - Caches preload promises to avoid duplicate loads
-
PreloadIndicatorComponent (/src/components/PreloadIndicator.tsx)- Visual feedback for active preloading
- Shows when routes are being preloaded in the background
- Animated lightning icon with queue count
-
Enhanced Navigation Menu (
/src/components/organisms/NavigationMenu.tsx)- Wrapped navigation items with hover detection
- Triggers preload on
mouseenterwith configurable delay - Cancels preload on
mouseleaveif not yet started
How It Works
1. Hover Detection
<div
onMouseEnter={() => handleItemHover(item.value)}
onMouseLeave={() => handleItemLeave(item.value)}
>
<NavigationItem ... />
</div>
2. Preload Initiation
When a user hovers over a navigation item:
- A 100ms timer starts (configurable)
- If hover continues, the route's component is queued for preload
- The
RoutePreloadManagerprocesses the queue with concurrency control (max 3 concurrent) - Component bundle is fetched and cached by the browser
3. Navigation
When the user clicks to navigate:
- If the route was preloaded, the component renders instantly (no loading spinner)
- If not preloaded, standard lazy loading occurs
4. Adjacent Route Preloading
On route change:
- The previous and next routes in the navigation order are automatically queued for preload
- This ensures smooth forward/backward navigation
5. Popular Route Preloading
After initial app load:
- A 1-second delay occurs
- Popular routes (dashboard, editor, models, components) are preloaded in the background
Configuration
Preload Strategy
// In route-preload-manager.ts
const DEFAULT_STRATEGY = {
preloadAdjacent: true, // Preload prev/next routes
preloadPopular: true, // Preload popular routes
maxConcurrentPreloads: 3, // Max parallel preloads
}
Hover Delay
// In NavigationMenu.tsx
const { preloadRoute, cancelPreload } = useRoutePreload({ delay: 100 })
Popular Routes
// In route-preload-manager.ts
const popularRoutes = new Set(['dashboard', 'editor', 'models', 'components'])
Performance Benefits
Before
- Navigation: Click → Loading spinner (1-3s) → Content
- User experience: Noticeable delay on every navigation
- Bundle loading: On-demand when user navigates
After
- Navigation: Click → Instant content (0ms perceived)
- User experience: Feels like a native desktop app
- Bundle loading: Proactive, during idle hover time
Metrics
- Instant navigation: Routes preloaded on hover load in ~0ms
- Adjacent preloading: Next/prev routes ready for sequential navigation
- Smart concurrency: Max 3 concurrent downloads prevent network saturation
- Cache efficiency: Preloaded components stay in browser cache
Console Logging
All preloading operations are thoroughly logged for debugging:
[PRELOAD] 🚀 Initiating preload for route: editor
[PRELOAD_MGR] 🎯 Queuing preload for route: editor (priority: low)
[PRELOAD_MGR] 🚀 Preloading editor → CodeEditor
[REGISTRY] 🎯 Preloading component: CodeEditor
[LAZY] 🎯 Preloading CodeEditor
[LAZY] ✅ CodeEditor preloaded
[PRELOAD] ✅ Route editor preload initiated
[PRELOAD_MGR] ✅ Route editor preloaded
Future Enhancements
- Predictive Preloading: Use navigation history to predict likely next routes
- Network-Aware: Reduce preloading on slow connections
- Priority Levels: User-triggered hovers get higher priority than automatic adjacent preloads
- Analytics Integration: Track preload hit rates and navigation patterns
- Configurable UI: Allow users to toggle preloading strategies in settings
API Reference
useRoutePreload(options?)
Hook for manual route preloading.
Options:
delay?: number- Delay before preload starts (default: 100ms)
Returns:
preloadRoute(pageId: string)- Initiate preloadcancelPreload(pageId: string)- Cancel pending preloadclearAllPreloads()- Clear all pending preloadsisPreloaded(pageId: string)- Check if route is preloaded
RoutePreloadManager
Global manager for preload strategies.
Methods:
setFeatureToggles(toggles)- Configure enabled routessetCurrentRoute(route)- Update current route (triggers adjacent preload)preloadRoute(pageId, priority?)- Queue route for preloadpreloadPopularRoutes()- Preload all popular routesisPreloaded(pageId)- Check preload statusgetStats()- Get current preload statisticsreset()- Clear all state
lazyWithPreload(importFn, key)
Create a preloadable lazy component.
Parameters:
importFn: () => Promise<{default: Component}>- Component import functionkey: string- Unique identifier for caching
Returns:
- Lazy component with
.preload()method
Best Practices
- Use hover delay: Don't preload on every hover - use a short delay (100-200ms)
- Limit concurrency: Cap concurrent preloads to avoid bandwidth issues
- Prioritize critical routes: Preload dashboard and main routes first
- Monitor performance: Use console logs and PreloadIndicator during development
- Test on slow connections: Ensure preloading doesn't hurt initial load time
Troubleshooting
Components not preloading
- Check that component is using
lazyWithPreloadincomponent-registry.ts - Verify component name matches page config in
pages.json - Check console for preload errors
Preloading too aggressive
- Increase hover delay:
useRoutePreload({ delay: 200 }) - Reduce max concurrent preloads in
route-preload-manager.ts - Disable popular route preloading
Memory concerns
- Preloaded components stay in browser cache (managed by browser)
- Cache is cleared on page refresh
- Use
routePreloadManager.reset()to manually clear
Related Files
/src/hooks/use-route-preload.ts- React hook/src/lib/route-preload-manager.ts- Manager class/src/lib/lazy-loader.ts- Lazy loading utilities/src/lib/component-registry.ts- Component registry with preload support/src/components/organisms/NavigationMenu.tsx- Navigation with hover detection/src/components/PreloadIndicator.tsx- Visual feedback component/src/App.tsx- Integration point