Skip to main content

Overview

Despia applications run on our GPU-accelerated native webview engine. With proper optimization, applications can achieve 60fps performance. While the Despia runtime handles core rendering optimizations, application performance depends on code structure, asset management, and efficient rendering strategies. Observed Performance:
  • Normal Operation: 60fps achievable with optimization
  • Low Power Mode: Typically ~30fps (based on extensive testing across devices)
Important: iOS aims to render at display refresh rate. Lower frame rates occur when applications cannot meet frame budgets under system constraints (Low Power Mode, thermal throttling, heavy workload).
This guide provides actionable patterns for building applications optimized for 60fps that degrade gracefully under constrained conditions.

Low Power Mode Considerations

Understanding Low Power Mode

Low Power Mode reduces background activity and caps ProMotion displays to 60Hz. It does not enforce a specific frame rate, but in practice, rendering performance is often affected.
Technical Note: iOS aims to render at display refresh rate (60Hz on standard displays, up to 120Hz on ProMotion). Low Power Mode does not set a “30fps limit.” However, based on extensive testing across devices, apps commonly render at approximately 30fps when Low Power Mode is active due to reduced performance headroom.
Normal Operation:
  • 60fps achievable performance
  • Full GPU acceleration
  • Smooth animations and interactions
Low Power Mode (Observed Behavior):
  • Apps typically render at ~30fps under Low Power Mode constraints
  • This occurs because reduced CPU/GPU headroom makes it difficult to meet 16.6ms frame budget
  • Still provides acceptable user experience for standard interactions
Why Frame Rates Drop: iOS always attempts to render at display refresh rate. Under Low Power Mode:
  • Reduced CPU/GPU performance allocation
  • Background work throttling
  • Thermal management constraints
  • Apps struggling to meet frame budget drop frames, often settling around 30fps
Optimization Strategy: Build for 60fps in normal operation. When properly optimized, applications maintain acceptable performance even under Low Power Mode constraints. Focus on:
  • Efficient JavaScript execution
  • GPU-accelerated animations
  • Minimal layout recalculations
  • Optimized asset loading

What Requires Optimization

Well-optimized interactions remain smooth even when frame rates drop:
  • Page transitions
  • Button taps and feedback
  • Modal animations
  • Content fades
  • List scrolling with momentum
  • Form interactions
Performance-critical scenarios:
  • Real-time games
  • Continuous drag-and-drop with complex visuals
  • High-speed animations with many elements
For standard applications (AI wrappers, consumer apps, business apps, community platforms, e-commerce, content apps), proper optimization ensures smooth performance across normal operation and constrained conditions (Low Power Mode, thermal throttling).

JavaScript Performance

Minimize Main Thread Blocking

Long-running JavaScript blocks the main thread and causes frame drops. Break up heavy computations:

Debounce High-Frequency Events

Scroll, resize, and input events fire rapidly. Limit execution frequency:

Use Passive Event Listeners

Mark event listeners as passive when they don’t call preventDefault():

Avoid Memory Leaks

Remove event listeners and clear timers when components unmount:

CSS Performance

Minimize Layout Thrashing

Batch DOM reads and writes separately:

Use Transform and Opacity for Animations

Transform and opacity properties are GPU-accelerated and don’t trigger layout:
Note: GPU-accelerated animations maintain 60fps smoothly. Transform and opacity changes are handled by the GPU, keeping the main thread free for other work.

Limit will-change Usage

will-change creates composite layers. Use sparingly and remove after animation:

Reduce Paint Complexity

Complex box shadows and gradients are expensive. Prefer simple styles:

Use contain Property

CSS containment optimizes rendering by limiting layout/paint scope:

Image Optimization

Use Appropriate Image Formats

  • JPEG: Photos and complex images
  • PNG: Images requiring transparency
  • WebP: Modern format with better compression (provide fallbacks)
  • SVG: Icons and simple graphics

Implement Lazy Loading

Defer offscreen images:

Optimize Image Dimensions

Serve images at display size, not larger:

Use Responsive Images

Serve different sizes based on viewport:

DOM Manipulation

Minimize DOM Access

Cache DOM queries:

Use Document Fragments

Batch DOM insertions:

Virtual Scrolling for Long Lists

For long lists (100+ items), use virtual scrolling to render only visible items. TanStack Virtual is proven to work exceptionally well with Despia. Installation:
Basic Implementation:
Dynamic Heights:
Horizontal Scrolling:
Why TanStack Virtual Works Well with Despia:
  • Optimized for high frame rates
  • Efficient DOM updates
  • Minimal re-renders
  • Handles dynamic content heights
  • Works seamlessly with Despia’s GPU-accelerated rendering
  • Supports horizontal and grid layouts
Performance Benefits:
  • Large datasets: Renders only visible items (typically 15-25 items)
  • Reduces memory usage significantly
  • Maintains smooth scrolling performance
  • Handles thousands of items efficiently

Memory Management

Avoid Global Variables

Global variables persist for the application lifetime:

Clear Large Data Structures

Explicitly null large objects when finished:

Use WeakMap for Object Metadata

WeakMaps allow garbage collection of keys:

Network Optimization

Minimize HTTP Requests

Combine resources where possible:

Use Resource Hints

Optimize resource loading:

Implement Efficient Caching

Configure cache headers appropriately:

Compress Assets

Enable gzip/brotli compression on server. Minify JavaScript and CSS:

Font Loading Optimization

Use font-display

Control font loading behavior:

Preload Critical Fonts

Subset Fonts

Include only required characters:

Third-Party Scripts

Load Scripts Asynchronously

Prevent blocking:

Lazy Load Non-Critical Scripts

Defer loading until needed:

Monitor Third-Party Impact

Use Performance API to measure:

Bundle Size Optimization

Code Splitting

Load code only when needed:

Tree Shaking

Ensure dead code is eliminated:
Recommended Libraries: These libraries are proven to work well with Despia and have minimal bundle impact:
  • TanStack Virtual (~5kb): Virtual scrolling for lists
  • date-fns (tree-shakeable): Date manipulation
  • zustand (~1kb): State management

Analyze Bundle Size

Identify large dependencies:

Performance Monitoring

Measure Frame Rate

Track rendering performance:
Typical Results:
  • Normal operation: 55-60fps (target)
  • Low Power Mode: ~30fps (observed across devices)
  • Heavy workload/thermal: Variable, often 30-45fps
  • Needs optimization: < 25fps consistently

Use Performance API

Measure critical operations:

Long Task Detection

Identify main thread blocking:

Common Performance Mistakes

Rendering Large Lists Without Virtualization

Impact: Large lists without virtualization cause significant frame drops and poor scroll performance. TanStack Virtual maintains smooth scrolling by rendering only visible items.

Excessive Re-renders

Synchronous localStorage

Inefficient Selectors

Missing Image Dimensions


Performance Budget

Define Targets

Set measurable performance goals:
Note: Optimize for 60fps. Proper optimization ensures acceptable performance (~30fps) under system constraints (Low Power Mode, thermal throttling).

Monitor Continuously

Track metrics in production:

Platform-Specific Considerations

iOS (WKWebView)

  • Memory limits are stricter (< 1.5GB typical)
  • JIT compilation available but with limits
  • Aggressive resource cleanup on background
  • IndexedDB has 50MB quota
Best Practices:
  • Keep memory usage under 1GB
  • Implement state persistence for background handling
  • Use sessionStorage for temporary data
  • Monitor memory with performance.memory (when available)

Android (WebView)

  • Performance varies significantly by device
  • Chromium-based (recent Android versions)
  • Hardware acceleration configurable
  • More generous memory limits on modern devices
Best Practices:
  • Test on low-end devices (2GB RAM)
  • Enable hardware acceleration
  • Use chrome://inspect for debugging
  • Implement graceful degradation for older Android versions

Despia-Optimized Libraries

These libraries have been tested extensively with Despia and provide excellent performance:

TanStack Virtual

Virtual scrolling for lists and grids. Handles large datasets efficiently with smooth scrolling performance.
Use cases:
  • Long lists (100+ items)
  • Infinite scroll feeds
  • Data tables
  • Grid layouts

TanStack Query

Data fetching and caching. Reduces redundant network requests and improves perceived performance.
Benefits:
  • Automatic background refetching
  • Optimistic updates
  • Request deduplication
  • Built-in caching

Date Libraries

For date manipulation, use tree-shakeable libraries:
Avoid moment.js (large bundle size).

State Management

Lightweight options that work well:
Avoid Redux if unnecessary (larger overhead).

Testing Performance

Device Testing

Test on representative devices: Minimum targets:
  • iOS: iPhone 12 or equivalent
  • Android: Device with 4GB RAM, mid-range processor
Observed frame rates:
  • Normal operation: 55-60fps (target)
  • Low Power Mode: ~30fps (typical)
  • Thermal throttling: Variable performance
Test for 60fps optimization. Also verify acceptable performance when Low Power Mode is enabled or under thermal constraints.

Performance Testing Tools

Synthetic Monitoring

Simulate network conditions:

Quick Reference

Critical Rendering Path

  1. Minimize critical resources
  2. Minimize critical bytes
  3. Minimize critical path length
  4. Prioritize visible content

Performance Checklist

  • Bundle size < 300kb gzipped
  • Images optimized and lazy loaded
  • CSS animations use transform/opacity only
  • Event listeners marked passive where applicable
  • Large lists use TanStack Virtual for virtualization
  • Third-party scripts loaded asynchronously
  • Resource hints configured
  • Service worker implemented for caching
  • Font loading optimized
  • No long-running JavaScript on main thread
  • Optimize for 60fps (degrades gracefully under system constraints)

Performance Metrics

Load Performance:
  • First Contentful Paint (FCP): < 1.5s
  • Largest Contentful Paint (LCP): < 2.5s
  • Time to Interactive (TTI): < 3.0s
Runtime Performance:
  • Frame rate (target): 60fps
  • Frame rate (Low Power Mode): ~30fps typical
  • Input latency: < 100ms
  • Cumulative Layout Shift (CLS): < 0.1

Optimization Priorities

  1. Critical: Reduce bundle size, optimize images, eliminate render-blocking resources
  2. Important: Implement caching, lazy loading, code splitting
  3. Nice to have: Advanced optimizations like resource hints, service workers, prefetching