Framework internals
Explore how Aurelia's compiler turns templates into instructions and how the runtime executes them.
This deep dive assumes you're comfortable with Aurelia's binding and component model. Bookmark it for debugging and tooling work.
Aurelia's instruction system is the bridge between template compilation and runtime execution. Templates compile to instruction objects that describe exactly what bindings and components to create, then renderers interpret these instructions to build the actual DOM bindings and component instances.
From Template to Runtime
Let's follow a simple template through the complete pipeline:
Template
<my-element value.bind="name" click.trigger="doSomething()">
<p>${message}</p>
</my-element>Compilation Phase
The template compiler processes this into instruction arrays:
const instructions = [
[ // Instructions for <my-element>
new HydrateElementInstruction(
'my-element', // Element name/definition
[ // Property instructions
new PropertyBindingInstruction('name', 'value', BindingMode.toView),
new ListenerBindingInstruction('doSomething()', 'click', false, null)
],
null, // Projections
false, // Containerless
[], // Captures
{} // Data
)
],
[ // Instructions for <p> inside my-element
new InterpolationInstruction('message', 'textContent')
]
];Runtime Phase
At runtime, renderers execute these instructions:
CustomElementRenderer creates the
my-elementcomponent instancePropertyBindingRenderer creates a binding from
nameto thevaluepropertyListenerBindingRenderer creates a click event listener
InterpolationRenderer creates a text binding for
${message}
All bindings are added to the component's controller and activated during the binding lifecycle.
Instruction Types and What They Do
Component Creation
hydrateElement- Creates custom element instanceshydrateAttribute- Creates custom attribute instanceshydrateTemplateController- Creates template controllers (if,repeat, etc.)
Data Binding
propertyBinding- Property bindings (.bind,.two-way, etc.)interpolation- Text interpolation${...}attributeBinding- Attribute bindings (.attr)stylePropertyBinding- Style bindings (.style)
Event Handling
listenerBinding- Event listeners (.trigger,.delegate,.capture)
Static Values
setProperty- Static property valuessetAttribute- Static attribute valuessetClassAttribute- Static class values
Advanced Features
refBinding- Reference bindings (refattribute)letBinding- Let bindings (letelement)iteratorBinding- Iterator bindings (forrepeat)
Debugging with Instructions
Inspecting Compiled Instructions
You can examine compiled instructions in the browser devtools:
Understanding Instruction Arrays
Instructions are organized as arrays where each array corresponds to a DOM target:
Debugging Binding Issues
When bindings don't work as expected:
Check what instructions were generated
Verify the instruction properties match your template
Look for missing or incorrect binding modes
Check if custom elements/attributes were resolved properly
Common Template Patterns
Basic Property Binding
Compiles to:
Event Binding
Compiles to:
String Interpolation
Compiles to:
Custom Element with Bindables
Compiles to:
Template Controller (Repeater)
Compiles to:
Extending the System
Creating Custom Instructions
For advanced scenarios, you can create custom instruction types:
Creating Custom Renderers
Custom renderers interpret your custom instructions:
Registering Custom Renderers
Register your renderer during app startup:
Resource Registration and Discovery
Before instructions can reference resources like custom elements, Aurelia needs to discover and register them. The framework supports multiple registration patterns.
Resource Registration Patterns
Decorator-Based Registration
The decorator automatically:
Creates a resource definition with metadata
Registers the resource in the DI container with key:
"au:resource:custom-element:user-card"Stores the definition for later compilation use
Static $au Property Registration
$au Property RegistrationConvention-Based Registration
With the conventions plugin, file names automatically determine resource names:
Resource Resolution During Compilation
When the template compiler encounters <user-card>, it:
Looks up the resource using
CustomElement.find(container, 'user-card')Resolves the definition from the DI container key
"au:resource:custom-element:user-card"Creates instruction with either the resource name string or the resolved definition
Caches the result to avoid repeated lookups
Resource Resolution During Runtime
At runtime, the CustomElementRenderer processes HydrateElementInstruction:
Container Hierarchy and Resource Scope
Resources are registered in DI containers, which form hierarchies:
Resource resolution follows the hierarchy:
Check current container
Check parent containers up to root
Return null if not found
Debugging Resource Registration
Check what resources are registered:
Resource Registration Best Practices
Use decorators for explicit control over resource configuration
Use static
$auproperties when decorators aren't suitable (e.g., plain classes)Use conventions for rapid development with consistent naming
Register global resources at app startup in
main.tsRegister page-specific resources in route components or modules
Understanding Aurelia's instruction system and resource registration gives you deeper insight into how templates become living, reactive UIs and provides the foundation for advanced framework extensions.
Last updated
Was this helpful?