Advanced Tutorial
Mobile Performance Optimization
Master advanced techniques for creating lightning-fast mobile experiences
90 min
Duration
Advanced
Level
4
Modules
Optimization Focus Areas
Key areas to focus on for mobile performance optimization
Touch & Interaction
Optimize for finger-based navigation
- 44px minimum touch targets
- Touch feedback animations
- Gesture support
- Scroll optimization
Network Adaptation
Efficient data usage and connectivity handling
- Adaptive loading
- Data compression
- Offline strategies
- Connection quality detection
Battery Efficiency
Minimize power consumption
- Reduce animations
- Optimize images
- Lazy loading
- Background task management
Performance Metrics
Monitor and optimize mobile-specific performance
- First Input Delay
- Time to Interactive
- Memory usage
- CPU efficiency
Implementation Guide
1
Touch-Optimized Interface
Design interfaces optimized for touch interaction
// Touch-optimized button component
export function TouchButton({
children,
variant = 'primary',
size = 'medium',
...props
}: TouchButtonProps) {
const sizeClasses = {
small: 'min-h-[40px] px-4 py-2 text-sm',
medium: 'min-h-[44px] px-6 py-3 text-base',
large: 'min-h-[48px] px-8 py-4 text-lg'
};
const variantClasses = {
primary: 'bg-blue-600 hover:bg-blue-700 text-white active:bg-blue-800',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-900 active:bg-gray-400'
};
return (
<motion.button
className={`
${sizeClasses[size]}
${variantClasses[variant]}
rounded-lg font-semibold transition-all duration-150
touch-manipulation select-none
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
active:scale-95
`}
whileTap={{ scale: 0.95 }}
transition={{ type: 'spring', stiffness: 400, damping: 30 }}
{...props}
>
{children}
</motion.button>
);
}
// Touch gesture hook
export function useTouch() {
const [touchStart, setTouchStart] = useState<Touch | null>(null);
const [touchEnd, setTouchEnd] = useState<Touch | null>(null);
const onTouchStart = (e: React.TouchEvent) => {
setTouchEnd(null);
setTouchStart(e.targetTouches[0]);
};
const onTouchMove = (e: React.TouchEvent) => {
setTouchEnd(e.targetTouches[0]);
};
const onTouchEnd = () => {
if (!touchStart || !touchEnd) return;
const distance = touchStart.clientX - touchEnd.clientX;
const isLeftSwipe = distance > 50;
const isRightSwipe = distance < -50;
return { isLeftSwipe, isRightSwipe, distance };
};
return { onTouchStart, onTouchMove, onTouchEnd };
}2
Network-Aware Loading
Adapt loading strategies based on network conditions
// Network-aware image loading
import { useState, useEffect } from 'react';
interface NetworkInfo {
effectiveType: '2g' | '3g' | '4g' | 'slow-2g';
downlink: number;
saveData: boolean;
}
export function useNetworkStatus() {
const [networkInfo, setNetworkInfo] = useState<NetworkInfo | null>(null);
useEffect(() => {
const updateNetworkInfo = () => {
if ('connection' in navigator) {
const connection = (navigator as any).connection;
setNetworkInfo({
effectiveType: connection.effectiveType,
downlink: connection.downlink,
saveData: connection.saveData
});
}
};
updateNetworkInfo();
if ('connection' in navigator) {
const connection = (navigator as any).connection;
connection.addEventListener('change', updateNetworkInfo);
return () => {
connection.removeEventListener('change', updateNetworkInfo);
};
}
}, []);
return networkInfo;
}
// Adaptive image component
export function AdaptiveImage({
src,
alt,
lowQualitySrc,
...props
}: AdaptiveImageProps) {
const networkInfo = useNetworkStatus();
const [imageSrc, setImageSrc] = useState(lowQualitySrc || src);
useEffect(() => {
if (!networkInfo) {
setImageSrc(src);
return;
}
// Use low quality image on slow connections or data saver mode
if (networkInfo.saveData || networkInfo.effectiveType === 'slow-2g' || networkInfo.effectiveType === '2g') {
setImageSrc(lowQualitySrc || src);
} else {
setImageSrc(src);
}
}, [networkInfo, src, lowQualitySrc]);
return (
<img
src={imageSrc}
alt={alt}
loading="lazy"
decoding="async"
{...props}
/>
);
}
// Preload critical resources based on network
export function useAdaptivePreload() {
const networkInfo = useNetworkStatus();
const preloadResource = (url: string, as: 'image' | 'script' | 'style') => {
if (!networkInfo) return;
// Skip preloading on slow connections
if (networkInfo.effectiveType === 'slow-2g' || networkInfo.effectiveType === '2g') {
return;
}
const link = document.createElement('link');
link.rel = 'preload';
link.href = url;
link.as = as;
document.head.appendChild(link);
};
return { preloadResource };
}3
Battery & Performance Optimization
Implement battery-efficient optimizations
// Battery-aware animations
export function useBatteryStatus() {
const [batteryInfo, setBatteryInfo] = useState<{
level: number;
charging: boolean;
chargingTime: number;
dischargingTime: number;
} | null>(null);
useEffect(() => {
const getBatteryInfo = async () => {
if ('getBattery' in navigator) {
const battery = await (navigator as any).getBattery();
const updateBatteryInfo = () => {
setBatteryInfo({
level: battery.level,
charging: battery.charging,
chargingTime: battery.chargingTime,
dischargingTime: battery.dischargingTime
});
};
updateBatteryInfo();
battery.addEventListener('chargingchange', updateBatteryInfo);
battery.addEventListener('levelchange', updateBatteryInfo);
return () => {
battery.removeEventListener('chargingchange', updateBatteryInfo);
battery.removeEventListener('levelchange', updateBatteryInfo);
};
}
};
getBatteryInfo();
}, []);
return batteryInfo;
}
// Power-efficient animation component
export function PowerEfficientAnimation({
children,
animate = true,
reduceMotion = false
}) {
const batteryInfo = useBatteryStatus();
const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
const shouldAnimate = useMemo(() => {
// Respect user preference
if (prefersReducedMotion || reduceMotion) return false;
// Disable animations on low battery
if (batteryInfo && batteryInfo.level < 0.2 && !batteryInfo.charging) {
return false;
}
return animate;
}, [animate, batteryInfo, prefersReducedMotion, reduceMotion]);
return (
<motion.div
animate={shouldAnimate ? { opacity: 1, y: 0 } : {}}
initial={shouldAnimate ? { opacity: 0, y: 20 } : {}}
transition={shouldAnimate ? { duration: 0.3 } : { duration: 0 }}
>
{children}
</motion.div>
);
}
// Memory-efficient list virtualization
export function VirtualizedList({ items, itemHeight = 50, containerHeight = 300 }) {
const [startIndex, setStartIndex] = useState(0);
const [endIndex, setEndIndex] = useState(0);
const visibleCount = Math.ceil(containerHeight / itemHeight);
const bufferSize = 5;
const onScroll = (e: React.UIEvent<HTMLDivElement>) => {
const scrollTop = e.currentTarget.scrollTop;
const newStartIndex = Math.floor(scrollTop / itemHeight);
const newEndIndex = Math.min(
newStartIndex + visibleCount + bufferSize,
items.length - 1
);
setStartIndex(Math.max(0, newStartIndex - bufferSize));
setEndIndex(newEndIndex);
};
const visibleItems = items.slice(startIndex, endIndex + 1);
return (
<div
style={{ height: containerHeight, overflowY: 'auto' }}
onScroll={onScroll}
>
<div style={{ height: startIndex * itemHeight }} />
{visibleItems.map((item, index) => (
<div
key={startIndex + index}
style={{ height: itemHeight }}
className="flex items-center px-4 border-b"
>
{item}
</div>
))}
<div style={{ height: (items.length - endIndex - 1) * itemHeight }} />
</div>
);
}4
Mobile-Specific Performance Monitoring
Track and optimize mobile performance metrics
// Mobile performance monitoring
export class MobilePerformanceMonitor {
private metrics: Map<string, number> = new Map();
constructor() {
this.setupObservers();
}
private setupObservers() {
// Monitor Long Tasks (>50ms)
if ('PerformanceObserver' in window) {
const longTaskObserver = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.warn(`Long task detected: ${entry.duration}ms`);
this.trackMetric('longTaskDuration', entry.duration);
});
});
try {
longTaskObserver.observe({ entryTypes: ['longtask'] });
} catch (e) {
console.warn('Long task monitoring not supported');
}
// Monitor Layout Shifts
const clsObserver = new PerformanceObserver((list) => {
let clsScore = 0;
list.getEntries().forEach((entry) => {
if (!(entry as any).hadRecentInput) {
clsScore += (entry as any).value;
}
});
this.trackMetric('cumulativeLayoutShift', clsScore);
});
try {
clsObserver.observe({ entryTypes: ['layout-shift'] });
} catch (e) {
console.warn('CLS monitoring not supported');
}
}
// Monitor memory usage (Chrome only)
if ('memory' in performance) {
setInterval(() => {
const memInfo = (performance as any).memory;
this.trackMetric('usedJSHeapSize', memInfo.usedJSHeapSize);
this.trackMetric('totalJSHeapSize', memInfo.totalJSHeapSize);
}, 30000);
}
}
trackMetric(name: string, value: number) {
this.metrics.set(name, value);
// Send to analytics service
if (typeof window !== 'undefined' && 'gtag' in window) {
(window as any).gtag('event', 'mobile_performance', {
metric_name: name,
metric_value: value,
user_agent: navigator.userAgent
});
}
}
getMetrics() {
return Object.fromEntries(this.metrics);
}
// Detect device capabilities
getDeviceInfo() {
const connection = (navigator as any).connection;
const deviceMemory = (navigator as any).deviceMemory;
const hardwareConcurrency = navigator.hardwareConcurrency;
return {
connectionType: connection?.effectiveType,
deviceMemory: deviceMemory || 'unknown',
cpuCores: hardwareConcurrency,
screenSize: {
width: screen.width,
height: screen.height,
pixelRatio: window.devicePixelRatio
},
viewport: {
width: window.innerWidth,
height: window.innerHeight
}
};
}
}
// Usage
export function usePerformanceMonitoring() {
useEffect(() => {
const monitor = new MobilePerformanceMonitor();
// Log device info on mount
console.log('Device Info:', monitor.getDeviceInfo());
return () => {
console.log('Performance Metrics:', monitor.getMetrics());
};
}, []);
}Best Practices
Touch Interface Design
- Minimum 44px touch targets
- Clear visual feedback for interactions
- Avoid hover states, use active states
- Design for one-handed use
Performance Optimization
- Optimize images for mobile screens
- Use efficient CSS animations
- Implement virtual scrolling for long lists
- Minimize JavaScript bundle size
Network & Battery
- Implement adaptive loading strategies
- Use service workers for offline support
- Respect data saver preferences
- Monitor battery status for animations
Mobile Performance Checklist
Progress: 0 / 8