# LiveComponents Performance Guide **Complete performance optimization guide for LiveComponents covering caching, batching, middleware, and optimization techniques.** --- ## Table of Contents 1. [Caching Strategies](#caching-strategies) 2. [Request Batching](#request-batching) 3. [Middleware Performance](#middleware-performance) 4. [Debounce & Throttle](#debounce--throttle) 5. [Lazy Loading](#lazy-loading) 6. [Island Components](#island-components) 7. [Fragment Updates](#fragment-updates) 8. [SSE Optimization](#sse-optimization) 9. [Memory Management](#memory-management) 10. [Performance Checklist](#performance-checklist) --- ## Caching Strategies ### Component-Level Caching Implement `Cacheable` interface for automatic caching: ```php #[LiveComponent('user-stats')] final readonly class UserStatsComponent implements LiveComponentContract, Cacheable { public function getCacheKey(): string { return 'user-stats:' . $this->state->userId; } public function getCacheTTL(): Duration { return Duration::fromMinutes(5); } public function shouldCache(): bool { return true; } public function getCacheTags(): array { return ['user-stats', 'user:' . $this->state->userId]; } public function getVaryBy(): ?VaryBy { return VaryBy::userId(); } public function getStaleWhileRevalidate(): ?Duration { return Duration::fromHours(1); } } ``` ### Cache Key Variations **Global Cache** (same for all users): ```php public function getVaryBy(): ?VaryBy { return VaryBy::none(); // Same cache for everyone } ``` **Per-User Cache**: ```php public function getVaryBy(): ?VaryBy { return VaryBy::userId(); // Different cache per user } ``` **Per-User Per-Locale Cache**: ```php public function getVaryBy(): ?VaryBy { return VaryBy::userAndLocale(); // Different cache per user and locale } ``` **With Feature Flags**: ```php public function getVaryBy(): ?VaryBy { return VaryBy::userId() ->withFeatureFlags(['new-ui', 'dark-mode']); } ``` ### Stale-While-Revalidate (SWR) Serve stale content while refreshing: ```php public function getCacheTTL(): Duration { return Duration::fromMinutes(5); // Fresh for 5 minutes } public function getStaleWhileRevalidate(): ?Duration { return Duration::fromHours(1); // Serve stale for 1 hour while refreshing } ``` **How it works**: - 0-5min: Serve fresh cache - 5min-1h: Serve stale cache + trigger background refresh - >1h: Force fresh render ### Cache Invalidation **By Tags**: ```php // Invalidate all user-stats caches $cache->invalidateTags(['user-stats']); // Invalidate specific user's cache $cache->invalidateTags(['user-stats', 'user:123']); ``` **Manual Invalidation**: ```php $cacheKey = CacheKey::fromString('user-stats:123'); $cache->delete($cacheKey); ``` --- ## Request Batching ### Client-Side Batching Batch multiple operations in a single request: ```javascript // Batch multiple actions const response = await LiveComponent.executeBatch([ { componentId: 'counter:demo', method: 'increment', params: { amount: 5 }, fragments: ['counter-display'] }, { componentId: 'stats:user-123', method: 'refresh' }, { componentId: 'notifications:user-123', method: 'markAsRead', params: { notificationId: 'abc' } } ]); ``` ### Server-Side Processing The framework automatically processes batch requests: ```php // BatchProcessor handles multiple operations $batchRequest = new BatchRequest(...$operations); $response = $batchProcessor->process($batchRequest); // Returns: // { // "success": true, // "results": [ // { "componentId": "counter:demo", "success": true, "html": "...", "fragments": {...} }, // { "componentId": "stats:user-123", "success": true, "html": "..." }, // { "componentId": "notifications:user-123", "success": true, "html": "..." } // ], // "totalOperations": 3, // "successCount": 3, // "failureCount": 0 // } ``` ### Batch Benefits - **Reduced HTTP Requests**: Multiple operations in one request - **Lower Latency**: Single round-trip instead of multiple - **Atomic Operations**: All succeed or all fail - **Better Performance**: Especially on slow networks --- ## Middleware Performance ### Middleware Overview Middleware allows you to intercept and transform component actions: ```php #[LiveComponent('user-profile')] #[Middleware(LoggingMiddleware::class)] #[Middleware(CachingMiddleware::class, priority: 50)] final readonly class UserProfileComponent implements LiveComponentContract { // All actions have Logging + Caching middleware } ``` ### Built-in Middleware **LoggingMiddleware** - Logs actions with timing: ```php #[Middleware(LoggingMiddleware::class, priority: 50)] ``` **CachingMiddleware** - Caches action responses: ```php #[Middleware(CachingMiddleware::class, priority: 100)] ``` **RateLimitMiddleware** - Rate limits actions: ```php #[Middleware(RateLimitMiddleware::class, priority: 200)] ``` ### Custom Middleware Create custom middleware for specific needs: ```php final readonly class PerformanceMonitoringMiddleware implements ComponentMiddlewareInterface { public function handle( LiveComponentContract $component, string $action, ActionParameters $params, callable $next ): ComponentUpdate { $startTime = microtime(true); $startMemory = memory_get_usage(); $result = $next($component, $action, $params); $duration = microtime(true) - $startTime; $memoryUsed = memory_get_usage() - $startMemory; // Log performance metrics $this->metricsCollector->record($component::class, $action, $duration, $memoryUsed); return $result; } } ``` ### Middleware Priority Higher priority = earlier execution: ```php #[Middleware(LoggingMiddleware::class, priority: 50)] // Executes first #[Middleware(CachingMiddleware::class, priority: 100)] // Executes second #[Middleware(RateLimitMiddleware::class, priority: 200)] // Executes third ``` **Execution Order**: 1. RateLimitMiddleware (priority: 200) 2. CachingMiddleware (priority: 100) 3. LoggingMiddleware (priority: 50) 4. Action execution ### Middleware Performance Tips ✅ **DO**: - Use caching middleware for expensive operations - Use logging middleware for debugging (disable in production) - Keep middleware lightweight - Use priority to optimize execution order ❌ **DON'T**: - Add unnecessary middleware - Perform heavy operations in middleware - Cache everything (be selective) - Use middleware for business logic --- ## Debounce & Throttle ### Client-Side Debouncing Debounce user input to reduce requests: ```javascript let searchTimeout; const searchInput = document.querySelector('[data-live-action="search"]'); searchInput.addEventListener('input', (e) => { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { LiveComponent.executeAction('search:demo', 'search', { query: e.target.value }); }, 300); // 300ms debounce }); ``` ### Client-Side Throttling Throttle frequent actions: ```javascript let lastExecution = 0; const throttleDelay = 1000; // 1 second function throttledAction() { const now = Date.now(); if (now - lastExecution < throttleDelay) { return; // Skip if too soon } lastExecution = now; LiveComponent.executeAction('component:id', 'action', {}); } ``` ### Server-Side Rate Limiting Use `#[Action]` attribute with rate limit: ```php #[Action(rateLimit: 10)] // 10 requests per minute public function search(string $query): State { return $this->state->withResults($this->searchService->search($query)); } ``` --- ## Lazy Loading ### Lazy Component Loading Load components when entering viewport: ```php // In template {{ lazy_component('notification-center:user-123', [ 'priority' => 'high', 'threshold' => '0.1', 'placeholder' => 'Loading notifications...' ]) }} ``` **Options**: - `priority`: `'high'` | `'normal'` | `'low'` - `threshold`: `'0.0'` to `'1.0'` (viewport intersection threshold) - `placeholder`: Custom loading text ### Lazy Island Components Use `#[Island]` for isolated lazy loading: ```php #[LiveComponent('heavy-widget')] #[Island(isolated: true, lazy: true, placeholder: 'Loading widget...')] final readonly class HeavyWidgetComponent implements LiveComponentContract { // Component implementation } ``` **Benefits**: - Reduces initial page load time - Loads only when needed - Isolated rendering (no template overhead) --- ## Island Components ### Island Directive Isolate resource-intensive components: ```php #[LiveComponent('analytics-dashboard')] #[Island(isolated: true, lazy: true)] final readonly class AnalyticsDashboardComponent implements LiveComponentContract { // Heavy component with complex calculations } ``` **Features**: - **Isolated Rendering**: Separate from main template - **Lazy Loading**: Load on viewport entry - **Independent Updates**: No parent component re-renders ### When to Use Islands ✅ **Use Islands for**: - Heavy calculations - External API calls - Complex data visualizations - Third-party widgets - Below-the-fold content ❌ **Don't use Islands for**: - Simple components - Above-the-fold content - Components that need parent state - Frequently updated components --- ## Fragment Updates ### Partial Rendering Update only specific parts of a component: ```html