Aura component architecture, events, server communication, and Aura-to-LWC migration strategies
From claude-sfdx-iqnpx claudepluginhub bhanu91221/claude-sfdx-iq --plugin claude-sfdx-iqThis skill uses the workspace's default tool permissions.
Process documents with Nutrient API: convert formats (PDF, DOCX, XLSX, images), OCR scans (100+ languages), extract text/tables, redact PII, sign, fill forms.
Provides Nuxt 4 patterns for hydration safety, SSR-safe data fetching with useFetch/useAsyncData, route rules for prerender/SWR/ISR, lazy loading, and performance optimization.
Guides Next.js 16+ Turbopack for faster dev via incremental bundling, FS caching, and HMR; covers webpack comparison, bundle analysis, and production builds.
An Aura component bundle consists of multiple files in a single directory:
| File | Purpose |
|---|---|
myComponent.cmp | Markup (HTML-like template) |
myComponentController.js | Client-side controller (action handlers) |
myComponentHelper.js | Reusable logic (called from controller) |
myComponentRenderer.js | Custom rendering lifecycle hooks |
myComponent.css | Component styles |
myComponent.design | Design attributes for Lightning App Builder |
myComponent.svg | Custom icon |
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
<aura:attribute name="accounts" type="Account[]" />
<aura:attribute name="isLoading" type="Boolean" default="false" />
<aura:attribute name="errorMessage" type="String" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:if isTrue="{!v.isLoading}">
<lightning:spinner alternativeText="Loading" />
</aura:if>
<aura:if isTrue="{!not(empty(v.errorMessage))}">
<div class="slds-text-color_error">{!v.errorMessage}</div>
</aura:if>
<aura:iteration items="{!v.accounts}" var="acc">
<p>{!acc.Name}</p>
</aura:iteration>
</aura:component>
The controller handles UI events and delegates logic to the helper. Keep controllers thin.
({
doInit: function(component, event, helper) {
helper.loadAccounts(component);
},
handleRefresh: function(component, event, helper) {
helper.loadAccounts(component);
}
})
({
loadAccounts: function(component) {
component.set("v.isLoading", true);
var action = component.get("c.getAccounts");
action.setParams({ status: "Active" });
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
component.set("v.accounts", response.getReturnValue());
component.set("v.errorMessage", null);
} else if (state === "ERROR") {
var errors = response.getError();
var message = (errors && errors[0] && errors[0].message)
? errors[0].message : "Unknown error";
component.set("v.errorMessage", message);
}
component.set("v.isLoading", false);
});
$A.enqueueAction(action);
}
})
All server calls go through $A.enqueueAction(). This queues the request and the framework batches multiple actions together.
var action = component.get("c.saveAccount");
action.setParams({ account: component.get("v.account") });
action.setStorable(); // enables client-side caching for read operations
action.setCallback(this, function(response) {
if (response.getState() === "SUCCESS") {
// handle success
}
});
$A.enqueueAction(action);
Rules:
ERROR and INCOMPLETE states in callbackssetStorable() for read-only actions to enable caching$A.enqueueAction() in a tight loop; batch parameters insteadsetBackground() for low-priority actions that should not block the UITravel up the containment hierarchy (child to parent). The parent must be a direct container.
<!-- Event definition -->
<aura:event type="COMPONENT" description="Account selected">
<aura:attribute name="accountId" type="Id" />
</aura:event>
<!-- Child fires the event -->
<aura:registerEvent name="onAccountSelect" type="c:AccountSelectedEvent" />
// Child helper
fireAccountSelect: function(component, accountId) {
var event = component.getEvent("onAccountSelect");
event.setParams({ accountId: accountId });
event.fire();
}
<!-- Parent handles the event -->
<c:accountRow onAccountSelect="{!c.handleAccountSelect}" />
Broadcast to all listeners in the application. Use sparingly as they are harder to trace and debug.
<aura:event type="APPLICATION" description="Global notification">
<aura:attribute name="message" type="String" />
<aura:attribute name="severity" type="String" />
</aura:event>
// Fire application event
var appEvent = $A.get("e.c:NotificationEvent");
appEvent.setParams({ message: "Record saved", severity: "success" });
appEvent.fire();
<!-- Any component can listen -->
<aura:handler event="c:NotificationEvent" action="{!c.handleNotification}" />
Decision Matrix:
| Scenario | Event Type |
|---|---|
| Child notifies direct parent | Component Event |
| Sibling communication | Application Event (or shared service component) |
| Global notification/toast | Application Event |
| Deeply nested child to ancestor | Application Event |
// Read attribute
var name = component.get("v.accountName");
// Write attribute
component.set("v.accountName", "New Value");
// Read server-side action
var action = component.get("c.getAccounts");
// Access body
var body = component.get("v.body");
Performance note: Each component.set() triggers re-rendering. Batch multiple attribute updates before setting them, or set a single object attribute rather than multiple primitives.
Aura supports component inheritance via the extends attribute. Use it for shared layouts or abstract base components.
<!-- Base component -->
<aura:component extensible="true" abstract="true">
<aura:attribute name="title" type="String" />
<div class="slds-card">
<h2>{!v.title}</h2>
{!v.body}
</div>
</aura:component>
<!-- Extending component -->
<aura:component extends="c:baseCard">
<aura:set attribute="title" value="Account Details" />
<p>Content goes here.</p>
</aura:component>
Rule: Prefer composition over inheritance. Deep inheritance chains are difficult to maintain and debug.
LWC components can be embedded inside Aura components. This is the primary interop pattern for gradual migration.
<!-- Aura wrapper -->
<aura:component implements="flexipage:availableForAllPageTypes">
<aura:attribute name="recordId" type="Id" />
<c:myLwcComponent record-id="{!v.recordId}" onaccountselected="{!c.handleSelection}" />
</aura:component>
Interop rules:
recordId becomes record-id)on prefix in Aura (accountselected becomes onaccountselected)Despite LWC being the recommended framework, Aura is still required in certain scenarios:
| Scenario | Reason |
|---|---|
lightning:overlayLibrary modals | LWC modal support added later but some orgs still use Aura modals |
| URL-addressable tabs (legacy) | Some legacy navigation patterns require Aura |
lightning:workspaceAPI (console apps) | Some workspace APIs only available in Aura |
| Wrapping LWC for App Builder | When LWC needs Aura-only interfaces |
| Existing large Aura apps | Migration cost may not justify immediate rewrite |
| Flow screen components (older) | Some legacy flow integrations require Aura |
| Aura | LWC Equivalent |
|---|---|
aura:attribute | @api property |
aura:handler name="init" | connectedCallback() |
component.get("v.x") | this.x |
component.set("v.x", val) | this.x = val (reactive) |
$A.enqueueAction() | @wire or imperative Apex import |
| Component Events | CustomEvent + dispatchEvent() |
| Application Events | lightning/messageService (LMS) |
aura:if | if:true / if:false or lwc:if / lwc:else |
aura:iteration | for:each / for:item |
$A.get("e.force:showToast") | import { ShowToastEvent } |
helper.js | Private methods in the component class |
renderer.js | renderedCallback() |
Aura (before):
// Controller
({
doInit: function(component, event, helper) {
var action = component.get("c.getAccounts");
action.setCallback(this, function(response) {
if (response.getState() === "SUCCESS") {
component.set("v.accounts", response.getReturnValue());
}
});
$A.enqueueAction(action);
}
})
LWC (after):
import { LightningElement, wire } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
accounts;
}
Salesforce has signaled that Aura is in maintenance mode. No new Aura features are being developed. The long-term direction is LWC. Plan migrations proactively: