Performance Guide
Optimize your QwickApps React Framework applications for maximum performance with data binding, component optimization, and caching strategies.
Overview
QwickApps React Framework is designed for performance out of the box, but understanding key optimization techniques will help you build faster, more responsive applications.
Data Binding Performance
Caching Strategies
Use CachedDataProvider for automatic performance optimization:
import { CachedDataProvider, JsonDataProvider } from '@qwickapps/schema';
const jsonProvider = new JsonDataProvider({ data: cmsData });
const cachedProvider = new CachedDataProvider(jsonProvider, {
maxSize: 100, // Cache up to 100 items
defaultTTL: 300000, // 5-minute cache TTL
enableMetrics: true // Track cache performance
});
Cache Hit Monitoring
Monitor cache performance in development:
const cacheMetrics = cachedProvider.getMetrics();
console.log('Cache hit ratio:', cacheMetrics.hitRatio);
console.log('Total requests:', cacheMetrics.totalRequests);
console.log('Cache size:', cacheMetrics.currentSize);
Optimized Data Sources
Structure data sources for efficient lookup:
// ✅ Efficient - specific paths
"company.header.title"
"pages.home.hero.subtitle"
"features.responsive.description"
// ❌ Inefficient - overly nested
"global.data.content.pages.home.sections.hero.blocks.title.text"
Component Optimization
Lazy Loading
Load heavy components on demand:
import { lazy, Suspense } from 'react';
const HeavyFeatureGrid = lazy(() => import('./HeavyFeatureGrid'));
function OptimizedSection() {
return (
<Section>
<Suspense fallback={<LoadingSpinner />}>
<HeavyFeatureGrid dataSource="features.grid" />
</Suspense>
</Section>
);
}
Memoization
Use React.memo for expensive components:
import { memo } from 'react';
const ExpensiveCard = memo(function ExpensiveCard({ data }) {
// Expensive calculations or rendering
return <div>{/* Complex UI */}</div>;
});
// Usage with data binding
<ExpensiveCard dataSource="cards.featured" />
Virtual Scrolling
For large lists, use virtual scrolling patterns:
import { FixedSizeList as List } from 'react-window';
function VirtualizedCardList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
<ProductCard dataSource={`products.${items[index].id}`} />
</div>
);
return (
<List
height={600}
itemCount={items.length}
itemSize={200}
>
{Row}
</List>
);
}
Image Optimization
Responsive Images
Optimize images for different screen sizes:
<CoverImageHeader
title="Hero Section"
backgroundImage={{
mobile: "/images/hero-400w.webp",
tablet: "/images/hero-800w.webp",
desktop: "/images/hero-1200w.webp",
large: "/images/hero-1600w.webp"
}}
loading="eager" // Above fold
/>
Lazy Loading Images
Load images below the fold lazily:
<FeatureCard
feature={{
title: "Feature Title",
image: "/images/feature.webp"
}}
loading="lazy" // Below fold
placeholder="/images/feature-placeholder.webp"
/>
WebP Format
Use modern image formats with fallbacks:
<picture>
<source srcSet="/image.webp" type="image/webp" />
<source srcSet="/image.jpg" type="image/jpeg" />
<img src="/image.jpg" alt="Description" />
</picture>
Bundle Optimization
Tree Shaking
Import only what you need:
// ✅ Efficient - tree-shakeable imports
import { Button, Section } from '@qwickapps/react-framework';
// ❌ Inefficient - imports entire library
import * as QwickApps from '@qwickapps/react-framework';
Code Splitting
Split code by route or feature:
// Route-based splitting
const HomePage = lazy(() => import('./pages/HomePage'));
const AboutPage = lazy(() => import('./pages/AboutPage'));
// Feature-based splitting
const AdminDashboard = lazy(() => import('./features/AdminDashboard'));
Dynamic Imports
Load components based on conditions:
async function loadComponent(componentType: string) {
switch (componentType) {
case 'chart':
return (await import('./ChartComponent')).default;
case 'map':
return (await import('./MapComponent')).default;
default:
return (await import('./DefaultComponent')).default;
}
}
Theme Performance
CSS Variables Optimization
Use CSS variables efficiently:
/* ✅ Efficient - minimal custom properties */
.component {
color: var(--theme-primary);
background: var(--theme-surface);
}
/* ❌ Inefficient - excessive custom properties */
.component {
color: var(--component-text-primary-color-light-mode-default);
background: var(--component-background-surface-color-light-mode-default);
}
Theme Switching Optimization
Optimize theme switching performance:
// Use CSS transitions for smooth theme changes
.qwick-app {
transition: background-color 0.2s ease, color 0.2s ease;
}
// Avoid JavaScript-heavy theme switching
const { setCurrentTheme } = useTheme();
setCurrentTheme('dark'); // Efficient - uses CSS variables
Memory Management
Data Provider Cleanup
Clean up data providers when components unmount:
useEffect(() => {
const provider = new JsonDataProvider({ data });
return () => {
provider.cleanup?.(); // Clean up resources
};
}, []);
Cache Size Limits
Set appropriate cache limits:
const cachedProvider = new CachedDataProvider(provider, {
maxSize: 50, // Reasonable limit for mobile
maxMemoryMB: 10, // Memory-based limits
cleanupInterval: 30000 // Regular cleanup
});
Performance Monitoring
Runtime Performance
Monitor component performance in development:
import { Profiler } from 'react';
function onRenderCallback(id, phase, actualDuration) {
console.log(`${id} (${phase}) took ${actualDuration}ms`);
}
<Profiler id="FeatureGrid" onRender={onRenderCallback}>
<FeatureGrid dataSource="features.main" />
</Profiler>
Data Binding Metrics
Track data binding performance:
const bindingMetrics = useDataBinding.getMetrics?.();
console.log('Average binding time:', bindingMetrics.averageTime);
console.log('Cache hit ratio:', bindingMetrics.cacheHitRatio);
Bundle Analysis
Analyze bundle size regularly:
# Analyze bundle composition
npm run build -- --analyze
# Check for unused dependencies
npx depcheck
# Measure bundle size impact
npx bundlephobia <package-name>
Performance Checklist
✅ Data Binding
- Use CachedDataProvider for frequently accessed data
- Structure data sources for efficient lookup
- Monitor cache hit ratios in development
- Set appropriate TTL values for different content types
✅ Components
- Lazy load components below the fold
- Use React.memo for expensive components
- Implement virtual scrolling for large lists
- Optimize re-render patterns with proper dependencies
✅ Images
- Use responsive image patterns
- Implement lazy loading for below-fold images
- Use modern formats (WebP) with fallbacks
- Optimize image sizes for different breakpoints
✅ Bundle
- Use tree-shakeable imports
- Implement code splitting by route/feature
- Analyze bundle size regularly
- Remove unused dependencies
✅ Theme
- Use efficient CSS variable patterns
- Optimize theme switching with CSS transitions
- Minimize custom property usage
- Cache theme calculations
Performance Targets
Loading Performance
- First Contentful Paint: < 1.5s
- Largest Contentful Paint: < 2.5s
- Time to Interactive: < 3.5s
- Cumulative Layout Shift: < 0.1
Runtime Performance
- Component Mount: < 16ms (60 FPS)
- Data Binding Resolution: < 5ms average
- Theme Switching: < 100ms
- Cache Hit Ratio: > 85%
Bundle Size Targets
- Initial Bundle: < 200KB gzipped
- Route Chunks: < 100KB gzipped each
- Vendor Chunks: < 150KB gzipped
- CSS Bundle: < 50KB gzipped
Troubleshooting
Common Performance Issues
Slow Data Binding
// Check cache configuration
const metrics = cachedProvider.getMetrics();
if (metrics.hitRatio < 0.8) {
// Increase cache size or TTL
}
Large Bundle Size
# Analyze what's causing bundle bloat
npm run build -- --analyze
npx webpack-bundle-analyzer build/static/js/*.js
Memory Leaks
// Ensure proper cleanup in useEffect
useEffect(() => {
const subscription = dataProvider.subscribe(callback);
return () => subscription.unsubscribe();
}, []);
What's Next?
- Data Binding Guide - Optimize data binding patterns
- Component Development - Build performant components
- Schema System - Efficient data validation
- Production Deployment - Deploy optimized applications