# Library Utilities
Core utility functions and modules for the CodeForge application.
## Module Overview
### `bundle-metrics.ts`
Bundle size and performance monitoring utilities.
**Key Functions:**
- `trackBundleLoad(chunkName, size)` - Track loaded chunks
- `getBundleMetrics()` - Get current bundle statistics
- `analyzePerformance()` - Analyze page load performance
- `startPerformanceMonitoring()` - Start monitoring resource loads
- `formatSize(bytes)` - Format byte sizes human-readable
**Usage:**
```typescript
import { startPerformanceMonitoring, analyzePerformance } from '@/lib/bundle-metrics'
// Start monitoring on app init
startPerformanceMonitoring()
// Analyze after page load
window.addEventListener('load', () => {
setTimeout(analyzePerformance, 1000)
})
```
### `component-registry.ts`
Centralized lazy-loaded component registry with preloading support.
**Registries:**
- `ComponentRegistry` - Main page components
- `DialogRegistry` - Dialog/modal components
- `PWARegistry` - PWA-related components
**Key Functions:**
- `preloadCriticalComponents()` - Preload dashboard & file explorer
- `preloadComponentByName(name)` - Preload specific component
**Usage:**
```typescript
import { ComponentRegistry, preloadCriticalComponents } from '@/lib/component-registry'
// Get a component
const Dashboard = ComponentRegistry.ProjectDashboard
// Preload on init
preloadCriticalComponents()
// Render lazily
}>
```
### `lazy-loader.ts`
Advanced lazy loading utilities with retry logic and preload support.
**Key Functions:**
#### `lazyWithRetry(componentImport, options)`
Lazy load with automatic retry on failure.
**Options:**
- `timeout` - Load timeout in ms (default: 10000)
- `retries` - Number of retry attempts (default: 3)
**Usage:**
```typescript
import { lazyWithRetry } from '@/lib/lazy-loader'
const HeavyComponent = lazyWithRetry(
() => import('./HeavyComponent'),
{ retries: 3, timeout: 15000 }
)
```
#### `lazyWithPreload(componentImport, preloadKey)`
Lazy load with manual preload capability.
**Usage:**
```typescript
import { lazyWithPreload } from '@/lib/lazy-loader'
const Dashboard = lazyWithPreload(
() => import('./Dashboard'),
'Dashboard'
)
// Later, trigger preload
Dashboard.preload()
```
#### `preloadComponent(componentImport)`
Preload a component without rendering it.
**Usage:**
```typescript
import { preloadComponent } from '@/lib/lazy-loader'
// Preload on hover
```
#### `createComponentLoader()`
Create a component loader with caching and tracking.
**Usage:**
```typescript
import { createComponentLoader } from '@/lib/lazy-loader'
const loader = createComponentLoader()
// Load component
const component = await loader.load('MyComponent', () => import('./MyComponent'))
// Check status
if (loader.isLoaded('MyComponent')) {
// Component ready
}
// Reset cache
loader.reset()
```
### `library-loader.ts`
Lazy loading utilities for heavy chart and visualization libraries.
**Supported Libraries:**
- Recharts (~450KB)
- D3 (~500KB)
- Three.js (~600KB)
- ReactFlow (~300KB)
**Key Functions:**
#### `loadRecharts()`, `loadD3()`, `loadThree()`, `loadReactFlow()`
Load libraries with retry logic and caching.
**Usage:**
```typescript
import { loadRecharts, loadD3 } from '@/lib/library-loader'
async function loadChart() {
const recharts = await loadRecharts()
// Use recharts
}
```
#### `preloadLibrary(libraryName)`
Preload library before it's needed.
**Usage:**
```typescript
import { preloadLibrary } from '@/lib/library-loader'
// Preload on hover
```
#### `clearLibraryCache()`
Clear all cached library imports.
**React Hooks:**
Use with hooks for automatic loading state management:
```typescript
import { useRecharts, useD3 } from '@/hooks'
function Chart() {
const { library: recharts, loading, error } = useRecharts()
if (loading) return
if (error) return Failed to load
if (!recharts) return null
const { LineChart } = recharts
return
}
```
**See `/docs/LAZY_LOADING_CHARTS.md` for complete documentation.**
### `utils.ts`
General utility functions (shadcn standard).
**Key Functions:**
- `cn(...inputs)` - Merge Tailwind class names with clsx + tailwind-merge
**Usage:**
```typescript
import { cn } from '@/lib/utils'
```
## Performance Best Practices
### 1. Choose the Right Lazy Loading Strategy
**Use `lazy()` for:**
- Standard components
- Low-priority features
- Small components
**Use `lazyWithRetry()` for:**
- Heavy components (Monaco Editor, D3 visualizations)
- Network-dependent components
- Critical but slow-loading features
**Use `lazyWithPreload()` for:**
- Frequently accessed components
- Components that benefit from hover preload
- Critical path components that need fast render
### 2. Preloading Strategy
**Immediate Preload:**
```typescript
// On app initialization
preloadCriticalComponents()
```
**Predictive Preload:**
```typescript
// Preload next likely components
useEffect(() => {
const nextPages = getAdjacentPages(currentPage)
nextPages.forEach(page => preloadComponentByName(page.component))
}, [currentPage])
```
**Interaction Preload:**
```typescript
// Preload on hover/focus
```
### 3. Bundle Monitoring
Always monitor bundle performance in development:
```typescript
import { startPerformanceMonitoring } from '@/lib/bundle-metrics'
// In main.tsx or App.tsx
startPerformanceMonitoring()
```
Watch console for:
- `[BUNDLE] 📦 Chunk loaded` - Individual chunk loads
- `[BUNDLE] 📊 Performance Analysis` - Overall metrics
- `[LOADER] 🔄 Loading component` - Component load attempts
- `[REGISTRY] 🚀 Preloading` - Preload operations
## Common Patterns
### Pattern 1: Dialog with Preload on Hover
```typescript
import { lazyWithPreload } from '@/lib/lazy-loader'
const SettingsDialog = lazyWithPreload(
() => import('./SettingsDialog'),
'SettingsDialog'
)
function App() {
return (
)
}
```
### Pattern 2: Heavy Component with Retry
```typescript
import { lazyWithRetry } from '@/lib/lazy-loader'
const CodeEditor = lazyWithRetry(
() => import('@monaco-editor/react'),
{ retries: 3, timeout: 20000 }
)
function EditorPage() {
return (
}>
)
}
```
### Pattern 3: Component Loader for Dynamic Imports
```typescript
import { createComponentLoader } from '@/lib/lazy-loader'
const loader = createComponentLoader()
async function loadPlugin(pluginName: string) {
try {
const plugin = await loader.load(
pluginName,
() => import(`./plugins/${pluginName}`)
)
return plugin
} catch (error) {
console.error(`Failed to load plugin: ${pluginName}`)
return null
}
}
```
## Troubleshooting
### Issue: Components not loading
**Check:**
1. Console for `[LOADER] ❌ Load failed` messages
2. Network tab for failed chunk requests
3. Chunk files exist in `dist/assets/` after build
**Solution:**
- Increase retry count or timeout
- Check network conditions
- Verify import paths are correct
### Issue: Slow initial load
**Check:**
1. Bundle size with `npm run build`
2. Number of synchronous imports
3. Critical path components
**Solution:**
- Move more components to lazy loading
- Reduce vendor bundle size
- Use code splitting more aggressively
### Issue: Preload not working
**Check:**
1. Console for `[REGISTRY] 🎯 Preloading` messages
2. Component has `preload()` method (use `lazyWithPreload`)
3. Preload called before render
**Solution:**
- Use `lazyWithPreload` instead of `lazy`
- Call `.preload()` method explicitly
- Check browser network tab for prefetch
## Testing
### Manual Testing
1. Open DevTools → Network tab
2. Filter by JS files
3. Interact with app and verify chunks load on-demand
4. Check console for bundle metrics
### Performance Testing
```typescript
// In test environment
import { analyzePerformance } from '@/lib/bundle-metrics'
window.addEventListener('load', () => {
const metrics = analyzePerformance()
expect(metrics.loadComplete).toBeLessThan(3000)
expect(metrics.resources.total.size).toBeLessThan(500000)
})
```
## Migration Guide
### From Eager Loading to Lazy Loading
**Before:**
```typescript
import HeavyComponent from './HeavyComponent'
function App() {
return
}
```
**After:**
```typescript
import { lazy, Suspense } from 'react'
const HeavyComponent = lazy(() => import('./HeavyComponent'))
function App() {
return (
}>
)
}
```
### From Basic Lazy to Lazy with Retry
**Before:**
```typescript
const Editor = lazy(() => import('./Editor'))
```
**After:**
```typescript
import { lazyWithRetry } from '@/lib/lazy-loader'
const Editor = lazyWithRetry(
() => import('./Editor'),
{ retries: 3 }
)
```