In this post, we’ll explore a few considerations and patterns for working with both Aura components and Lightning web components in your Salesforce applications. We’ll look at general usage patterns for combining Aura and Lightning web components in your apps, as well as considerations for migrating components and ways to identify initial migration opportunities.
If you’ve missed our posts about the new programming model for Lightning components, you should check out our announcement post and our overview of the Sample App updates we’ve made to showcase the new choices available for Lightning development.
Using Aura and Lightning web components together
Aura components and Lightning web components work together in many different ways, and in ways that are not visible to end users of your applications. In fact, you’ve been interacting with Lightning web components in Lightning Experience for some time. If you’re looking to use Aura components and Lightning web components together in your applications, or wondering about the possibilities, there are two composition strategies to consider: nested and side-by-side. Let’s look at both of these strategies.
Nested composition
In scenarios involving both Aura components and Lightning web components in parent-child relationships, you’ll want to think of Aura as the ultimate parent. You can have both Aura components and Lighting web components inside a parent Aura component, but Lightning web components can only contain other Lightning web components.
Let’s look at an example:
In this example of a custom Lightning app page, we’ve got two ‘parent’ components on the page: an Aura component on the left and a Lightning web component on the right. The Aura component has two child components: another Aura component and a Lightning web component. The other parent, our Lightning web component, also has two children. Both children are Lightning web components.
Side-by-side composition
To understand how Aura components and Lightning web components can work side-by-side, let’s return to our example above. On our custom Lightning app page, we have an Aura component and a Lighting web component. The two components can pass information back and forth, whether that information is coming in through user interaction with the app page, or events triggered by actions outside the app page.
Let’s walk through this example. Our Aura component on the left has the ability to send and receive information in a few different ways: by interacting directly with child component attributes or through application and component events —whether those are standard Aura events or custom Aura event bundles you define. Our Lightning web component on the right also has different ways to communicate: it can send and receive information through JavaScript CustomEvent objects, as well as interacting with child component methods and properties exposed through public APIs. Both Aura and Lightning web components can send and receive data through Lightning Data Service (LDS) and the User Interface API.
In the Spring ’19 release, a mechanism for communication between Aura components and Lightning web components that aren’t in the same component hierarchy isn’t provided by the platform. You can implement a custom service to support this type of communication, which you’ll see at work in our sample applications. This capability will be available in future releases as a part of the Lightning Event Service, which is what you see in the diagram above.
You can explore quick examples of these ideas in our Recipes sample app, on the Aura Interoperability tab. For more information about event migration and the underlying issues posed by application-wide events, check out the Lightning Web Components Developer Guide.
Choosing between Aura and Lightning Web Components
For the most part, if you’re building brand new functionality, you should look at building with Lightning web components first. Your applications will get the benefit of increased native operation in the browser, which translates to faster app performance and more functionality. As a developer, you’ll also benefit. In addition to the powerful tools provided by Salesforce, the Lightning web components model is compatible with resources and tools used by web developers everywhere, like popular tools for linting or formatting your code, or JavaScript testing frameworks like Jest. (In an upcoming post, we’ll go into unit testing your Lightning web components with Jest.)
However, there are some places where functionality available to Aura components isn’t yet fully supported in Lightning web components. In these cases, you’ll need to determine if you can build most of your application with Lightning web components and add key functionality with an Aura wrapper, or if you need to build more functionality with Aura components.
What isn’t yet AVAILABLE in Lightning Web Components?
Lightning web components support most of the functionality available in Aura components. (The Lightning Web Components developer guide has a mapping of many of the features available in Aura, and their equivalents.) There are some exceptions you’ll want to note when thinking about composition or planning for migration. Here’s a list of what’s not yet available:
Interfaces:
- clients:availableForMailAppAppPage
- clients:hasEventContext
- clients:hasItemContext
- force:appHostable
- forceCommunity:layout
- forceCommunity:profileMenuInterface
- forceCommunity:searchInterface
- forceCommunity:themeLayout
- lightning:appHomeTemplate
- lightning:availableForChatterExtensionComposer
- lightning:availableForChatterExtensionRenderer
- lightning:availableForFlowActions
- lightning:availableForFlowScreens
- lightning:homeTemplate
- lightning:isUrlAddressable
- lightning:recordHomeTemplate
- lightningsnapin:minimizedUI
- lightningsnapin:prechatUI
- ltng:allowGuestAccess
Components:
- aura:token
- force:canvasApp
- lightning:flow
- lightning:container
- lightning:listView
- lightning:overlayLibrary
- lightning:path
- lightning:picklistPath
- lightning:quipCard
- lightning:select (replaced by lightning-combobox)
- lightning:unsavedChanges
- forceChatter namespace components
- forceCommunity and lightningCommunity namespace components
- lightningsnapin namespace components
- wave namespace components
UI namespace components have no equivalent in Lightning web components.
Event tags and types:
- aura:registerEvent*
- aura:handler*
- Aura application events
There is no direct replacement in Lightning web components for aura:handler/registerEvent. If you’ve used these tags to create and handle custom component events in Aura, this functionality is available through CustomEvent objects in Lightning web components.
API services:
- conversationToolkitAPI
- empApi
- navigationItemAPI
- omniToolkitAPI
- quickActionAPI
- utilityBarAPI
- workspaceAPI
When supported, these APIs will be available using module import syntax.
Migrating from Aura Components to Lightning Web Components
The Lightning Web Components Developer Guide goes into detail about migration patterns for HTML markup, JavaScript and other parts of your Aura component bundles. But how do you decide what needs to migrate? What characteristics should initial migration projects have in common?
In our experience, migration follows three general patterns. Let’s walk through these patterns from simplest to most complex.
Pattern #1: Swap and go
Best for: Individual components (standalone or child components inside a component hierarchy) with little to no JavaScript, with functionality that is fully supported in Lightning web components.
What this looks like:
- Swap HTML syntax from your Aura component for the direct counterpart in your new Lightning web component. An example of this would be
<lightning:recordForm>
becoming<lightning-record-form>
. See the Developer Guide for more in-depth examples of migrating HTML syntax.
Pattern #2: Redesign, then rebuild
Best for: Individual components (standalone or child components inside a component hierarchy) with JavaScript files. Components with <aura:method> references. Components with functionality not yet available in Lightning web components.
What this looks like:
- Refactor discreet controller and helper files into a single, coherent ES6 module. The Modern Javascript Development module on Trailhead has a great overview of the constructs and patterns you’ll use.
- Migrate supported interfaces to XML tags in your component *.js-meta.xml files
- Re-evaluate component event structure.
- Migrate <aura:method> to @api decorated functions.
- Migrate custom Aura component events to either standard DOM events or CustomEvent objects. (See the irrigationDialog in Pure Aloe or imageGallery in Easy Spaces.)
- Re-evaluate how you’re using Apex and optimize for performance.
- Use Lightning Data Service instead of Apex for single record patterns when possible. Examples include the brokerCard in DreamHouse, the bundle component in Pure Aloe, or the customerDetailForm in Easy Spaces.
- Use Apex invocations decorated with @wire when possible. There are many examples of this in the sample apps, like the harvestFieldList in Pure Aloe or relatedSpaces in Easy Spaces. For usage with Apex performing dynamic query selections and pagination, see the fundTileList in DreamInvest, or productTileList in Ebikes.
- Reserve imperative Apex for methods involving DML that cannot be accomplished via Lightning Data Service, or when you need to invoke Apex based on user interaction (like the ApexImperativeMethod Recipe).
- Use a lightweight Aura parent component wrapper to preserve functionality not yet supported in Lightning web components. Check out examples of these kinds of wrappers in Easy Spaces and Pure Aloe.
Pattern #3: START from the BOTTOM up
Best for: Complex components with multiple child hierarchies, deeply nested component hierarchies.
What this looks like:
- Begin migration with the lowest-level child component. Continue migration at the same level of the component hierarchy until every lowest-level child is migrated.
- Continue working up the hierarchy from the bottom, one layer at a time.
- Apply principles of the above patterns to components within your hierarchies.
- Abstract functionality not yet available in Lightning web components to the highest possible Aura parent layer. Use the wrapper pattern described above.
Keep in mind that these patterns aren’t mutually exclusive. Identifying these patterns in your applications can help you break down a complex project into clear, distinct steps.
As you start planning for migration, lean towards initial projects that involve functionality that has a clear equivalent in Lightning web components. As you start to get comfortable with designing and using Lightning web components, you’ll find it easier to move on to projects involving more complex redesigns or addressing functionality without a direct equivalent in Lightning web components.
As you actually work on your migration, you’ll apply techniques from each of these patterns interchangeably. You may find yourself using the syntax swapping from pattern #1 as the first step of migrating an individual component while following pattern #3. In order to make a plan for migrating a complex application with pattern #3, you’ll need to think about how to use techniques from patterns #1 and #2 throughout the component hierarchy.
What’s next and what to do now
In future posts, we’ll go deeper into the patterns and decisions behind our Trailhead Sample Apps migrations from Aura to Lightning web component versions.
In the meantime, you can start to explore Lightning Web Components for yourself and connect with other developers in your community with these resources:
- Lightning Web Components Video Gallery
- Build Lightning Web Components (Trailhead)
- Lightning Web Components for Aura Developers (Trailhead)
- Sample Apps Gallery (Trailhead)
- Set Up Your Lightning Web Components Developer Tools (Trailhead)
Don’t forget that you can also learn about LWC with your local Trailblazer Community in-person! Join us for Global Developer Week – find and RSVP to a meeting today.