Performance optimization techniques | The Aurelia 2 Docs

Performance optimization techniques

This guide covers advanced performance optimization techniques for Aurelia applications, including framework-specific optimizations, build configuration, and best practices for high-performance applications.

Framework-Specific Optimizations

The Aurelia task queue provides several performance optimization features:

Batch DOM updates to improve rendering performance:

import { batch } from 'aurelia';

// Batch multiple DOM updates in a single frame
batch(() => {
  // both assignment will not immediately trigger rerendering
  component.prop = someValue;
  component2.prop = someOtherValue;
});

// With mordern browser implementation, normally all DOM changes execute in the same task
// and without triggering layout-ing or reflow unless there's a DOM property read in between
// that triggers those.
element1.style.left = '100px';
element2.style.top = '200px';
element3.textContent = 'Updated';

State Management Performance

Use the built-in memoization system for expensive computations:

Share memoized selectors across components for better performance:

Computed Observer Performance

Sync vs Async Flush Modes

Choose the appropriate flush mode for computed properties:

Computed Property Optimization

Optimize computed properties for better performance:

Manual computed dependencies declaration

Read more on @computed decorator here.

Watch Performance Optimization

Efficient Watch Expressions

Use efficient watch expressions to minimize performance impact:

Control when watch callbacks execute:

Binding Behaviors for Performance

Throttle Binding Behavior

Limit how often a binding updates, useful for expensive operations triggered by user input:

Debounce Binding Behavior

Delay binding updates until user stops typing, ideal for search-as-you-type:

Performance Tips:

  • Use throttle for continuous events (scroll, mousemove, resize)

  • Use debounce for discrete user input (typing, form fields)

  • Throttle allows periodic updates; debounce waits for quiet period

  • Default delay is 200ms if not specified

Virtual Repeat Performance

Optimize Virtual Repeat for Large Collections

Configure virtual-repeat inline for optimal performance with large datasets:

Virtual Repeat with Variable Heights

For items with varying heights, enable the variable-height option:

Performance Note: Variable sizing has more overhead than fixed sizing. Use fixed heights when possible for best performance.

Tree Shaking Configuration

Configure your bundler for optimal tree shaking:

Import only what you need from Aurelia packages:

Route-Based Code Splitting

Split your application by routes for better loading performance:

Component-Based Code Splitting

Split large components into separate chunks:

Minification and Compression

Configure production builds for optimal performance:

Service Worker Integration

Implement caching strategies for better performance:

Proper Event Listener Cleanup

Avoid Circular References

Use WeakMap for storing metadata that should be garbage collected:

Batch Multiple State Changes

When making multiple property changes, use batch() to combine them into a single change notification:

Batch multiple array operations to prevent repeated re-renders:

Performance Benefits:

  • Reduces the number of change notifications

  • Prevents unnecessary intermediate UI updates

  • Particularly effective when updating multiple related properties

  • Essential for bulk data operations

Runtime Performance Profiling

Performance Metrics Collection

Real-World Performance Scenarios

Scenario 1: Optimized Data Grid

Build a high-performance data grid with 10,000+ rows:

Performance Features Used:

  • debounce prevents filtering on every keystroke

  • virtual-repeat renders only visible rows

  • @computed with explicit deps caches filter results

  • Fixed item-height enables optimal scrolling

Scenario 2: Real-Time Dashboard Updates

Handle high-frequency updates efficiently:

Performance Features Used:

  • batch() combines multiple updates into one notification

  • Persistent task with delay for regular updates

  • Task cancellation on component detach prevents leaks

Optimize large image galleries:

Performance Features Used:

  • variable-height handles different aspect ratios

  • Native lazy loading with loading="lazy"

  • Task queue prevents UI blocking during data loading

  • Chunked loading for progressive rendering

Scenario 4: Complex Form with Validation

Optimize forms with many fields:

Performance Features Used:

  • debounce on inputs reduces validation frequency

  • batch() when loading initial form data

  • Async flush for validation computation

  • Object.assign for efficient property updates

  • Use batch for array mutation operations

  • Implement memoization with createStateMemoizer for expensive state computations

  • Choose appropriate flush modes (sync or async) for computed properties

  • Optimize watch expressions and prefer computed properties

  • Use throttle for continuous events, debounce for discrete user input

  • Enable deep observation only when needed for nested objects

  • Always clean up event listeners and subscriptions in detaching()

  • Use WeakMap for metadata storage that should be garbage collected

  • Avoid circular references or use explicit cleanup

  • Cancel persistent tasks when components detach

  • Monitor memory usage during development

  • Implement virtual-repeat for lists with 100+ items

  • Use fixed item-height for best virtual-repeat performance

  • Enable variable-height only when necessary

  • Use pagination or infinite scroll for large datasets

  • Process data in batches with batch() to avoid blocking the UI

  • Stream large datasets when possible using task queue

  • Use debounce on form inputs (300-500ms for text, 200ms for other fields)

  • Use throttle on scroll/resize/mousemove handlers (100-200ms)

  • Batch multiple observable changes with batch()

  • Prefer @computed with explicit deps over complex expressions in templates

  • Use flush: 'async' (default) unless immediate updates are critical

  • Configure tree shaking properly in your bundler

  • Use code splitting for routes and large components

  • Optimize bundle size with selective imports

  • Implement service worker caching for production apps

  • Minify and compress assets

6. Performance Monitoring

  • Monitor component lifecycle performance

  • Track memory usage patterns with browser DevTools

  • Use performance metrics to identify bottlenecks

  • Test with realistic data volumes

These optimization techniques will help you build high-performance Aurelia applications that scale well and provide excellent user experiences.