Working with Aura and Lightning Web Components: Interoperability and Migration

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. 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.

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

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.