Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Migrate To Lightning Web Components from Aura framework to increase performance


Published on

Migrate To Lightning Web Components from Aura framework to increase performance of Lightning Components

Published in: Software

Migrate To Lightning Web Components from Aura framework to increase performance

  1. 1. Migrate to LWC To increase performance 2019
  2. 2. Introduction Bohdan Dovhan - Senior Salesforce Developer and Salesforce Development Team Lead Salesforce Certified Development Lifecycle & Deployment Designer Salesforce Certified Platform Developer I Salesforce Certified Platform Developer II Salesforce Certified Platform App Builder 8 years of Development experience 5 years of Development on Salesforce platform
  3. 3. SF UI Dev Tools Salesforce: point-and-click tools and development tools UI Development frameworks: Visualforce Lightning Aura Components Lightning Web Components (Brand new since Spring’19 release) UI Development Tools: Developer Console, many IDEs (VF, Aura) VS Code (LWC, Aura, VF) Does your IDE support LWC development? If it does not, migrate to VS Code
  4. 4. LWC Lightning web components (LWC) are a new programming model for the Lightning Component Framework that is released in the Spring `19 release and is available since December of 2018. This programming model is architected with three principles in mind. Align with modern web standards Interoperability with the original Aura-based Lightning development model Better Performance LWC are compliant with most ES2015 (also known as ES6) and later standards that have seen good adoption across modern browsers. LWC are more secure, since they add CSS isolation, script isolation, DOM isolation, and a more limited event scope. LWC have better performance because of leveraging native DOM support. LWC can be unit tested with Jest framework but such tests are not stored in Salesforce, these tests cannot be run on cloud. Node.js, npm and Jest should be installed on Developer machine to be able to run them.
  5. 5. Aura vs LWC
  6. 6. LWC Migration Plan Aura Components can contain LWC. LWC cannot contain Aura Components. 1. To develop brand new UI: try to use LWC 2. To increase performance: refactor slowest children to LWC or everything 3. If feature is not supported by LWC: use Aura completely or wrap LWC with Aura At the current Spring 19 release Lightning Web Components are not supported in Lightning Actions, Utility Bar, Console, Flows, Visualforce pages and external systems
  7. 7. Prerequisites LWC cannot be developed in Developer Console. VS Code with Salesforce Extensions pack is recommended (however any other editor can be used). LWC requires version 45 (Spring 19)
  8. 8. ES6 Compliance The JavaScript language and web standards, such as HTML templates, custom elements, and web components have evolved significantly in the last few years. Many modern HTML and CSS features developed recently and used by Frontend developers in other technologies were not available to Lighting Developers since these features were not supported by proprietary Aura Javascript framework. Lightning Web Components bring modern JavaScript and web standards to the Lightning Component framework. Lightning Web Components is an implementation of the W3C’s Web Components standards. It supports the parts of Web Components that perform well in browsers, and adds only what’s needed to work in all browsers supported by Salesforce. Web standards usage boosts performance because more features are executed natively by the modern browser instead of by a JavaScript framework. Salesforce promises quicker rendering time for LWC
  9. 9. LWC Building blocks There are two types of LWC: UI components and service components. HTML File (expected for UI Components, optional for service components) Javascript File (always required) Configuration File (always required) CSS file (optional) Lightning web component’s JavaScript file is just an ES6 module which imports dependencies, defines properties and methods and exports them. To reuse code in Aura Component C of Aura Components A and B, A should inherit B or vice versa and then C can inherit A or B to reuse both code of A and B To reuse code in Lightning Web Component C of LWC A and B, C can import two modules A and B. A doesn’t require to import B and B doesn’t require to have A imported.
  10. 10. Create SFDX Project To work with Lightning Web Component, SFDX project should be created first to be able to deploy and retrieve source by using corresponding force:source:deploy and force:source:retrieve commands. To create SFDX project in Visual Studio Code, we need to invoke hot key combination Ctrl-Shift-P in Windows (or Cmd-Shift-P in Macs) and then either select or type SFDX: Create Project and select a name for it, like “demo”. Watch this video GIF image to see this in action. Also SFDX Project can be created by command line directly
  11. 11. Create Lightning To create Lightning Aura Component, menu item SFDX: Create Lightning Component can be used and name for a component should be chosen, like AuraCmp To display output panel and monitor which SFDX command is executed under hood, a key combination Ctrl-Shift-U can be used on Windows (or Cmd-Shift-U on Macs) or corresponding menu item can be used. In Output panel dropdown Salesforce CLI should be selected to be able to see SFDX commands run in the background.
  12. 12. Create Aura Comp As we can see, command sfdx force:lightning:component:create --componentname AuraCmp --outputdir force- appmaindefaultaura is run under the hood. We can run in terminal to create another Aura component with name AuraCmpHello. To switch to Terminal we can use hot key combination Ctrl-` or Cmd-`or View Terminal menu item. To see created component we can click Refresh Explorer button. sfdx force:lightning:component:create --componentname AuraCmpHello --outputdir force-appmaindefaultaura
  13. 13. Create LWC Lightning Aura Components are stored in `aura` subfolder while Lightning Web Components are stored in `lwc` subfolder. So to create Lightning Web Component we need to click SFDX: Create Lightning Web Component menu item on `lwc` subfolder. Let’s create lwcHello component using menu item.
  14. 14. Create in terminal Lightning Aura Components are stored in `aura` subfolder while Lightning Web Components are stored in `lwc` subfolder. So to create Lightning Web Component we need to click SFDX: Create Lightning Web Component menu item on `lwc` subfolder. Let’s create lwcHello component using menu item. We can notice that this command sfdx force:lightning:component:create --type lwc --componentname lwcHello --outputdir force-appmaindefaultlwc is executed by the Visual Studio, which looks very similar to the command used to create Lightning Aura Components, please note the different parts: --type lwc attribute and different location ending. Let’s use this command from terminal to create another Lightning Web Component called helloWebComponent sfdx force:lightning:component:create --type lwc --componentname helloWebComponent --outputdir force-appmaindefaultlwc
  15. 15. Metadata API LWC? How do I retrieve Lightning Web Components using Ant Migration tool or mdapi:retrieve command from SFDX? What is appropriate metadata API component which corresponds to LWC folder components in sfdx? The new Metadata API component is called LightningComponentBundle The following XML code should be added to package.xml for Ant or force:mdapi:retrieve SFDX command: <types> <members>*</members> <name>LightningComponentBundle</name> </types> SFDX command sfdx force:source:retrieve -m LightningComponentBundle can be used as well to retrieve lwc folder.
  16. 16. Migrate Bundle Files Aura and LWC have similar but different structure. Aura components have multiple Javascript files while LWC have the only Javascript file which is also an ES6 Javascript module as we pointed in the LWC Building Blocks section. How can we migrate existing Aura Component Bundle Files to Lightning Web Component structure? Salesforce documentation provides the following table to address this question. RESOURCE AURA FILE LWC FILE Markup sample.cmp sample.html Controller sampleController.js sample.js Helper sampleHelper.js sample.js Renderer sampleRenderer.js sample.js CSS sample.css sample.css Documentation sample.auradoc Not currently available Design sample.js-meta.xml SVG sample.svg Not currently available
  17. 17. Access Control How can we migrate Aura Component access control to Lightning Web Components? The mechanism for access control is different in a Lightning web component from access attribute of a component or attribute in Aura framework. In Lightning Web Components access is rather defined by JavaScript property decorators and the component’s configuration file. If Aura Component access is global or if it is designed to be placed in Community Builder or App builder then its LWC counterpart should have value  <isExposed>true</isExposed> in the component’s configuration file. If Aura Component access is public and it is not designed to be placed in Community Builder or App builder, it should have value <isExposed>false</isExposed> in the component’s configuration file. Public and global attributes in Aura component should be declared in LWC component Javascript module with @api decorator. Private attributes in Aura component  should be declared in LWC component Javascript module with @track decorator if component should be refreshed on attribute value changes or without any decorators otherwise.
  18. 18. Aura Access Example How can we migrate Aura Component access control to Lightning Web Components? See the following component example <aura:component> <aura:attribute name="recordId" type="Id" access="global" /> <aura:attribute name="property" type="Property__c" access="public" default="{Name:'Myself'}"/> <aura:attribute name="message" type="String" access="private" default="Hello"/> <aura:attribute name="unbound" type="String" access="private" default="Hi"/> {!v.recordId}<br/> {!}<br/> {!v.message}<br/> {#v.unbound}<br/> <lightning:input label="Message" value="{!v.message}"/> </aura:component>
  19. 19. LWC Access Example How can we migrate Aura Component access control to Lightning Web Components? See the LWC counterpart <template> {recordId}<br/> {property.Name}<br/> {message}<br/> {unbound}<br/> <lightning-input label="Message" value={message} onchange={changeHandler}> </lightning-input> </template> Global recordId receives @api decorator. The @api decorator defines a public reactive property. Public property receives @api decorator. Private message referenced by bound expression receives @track decorator. Private reactive properties rerender a component when their value is changed. Private unbound referenced only by unbound expressions doesn’t decorators. import { LightningElement, api, track } from 'lwc’; export default class Mig extends LightningElement { @api recordId; @api property = {Name:'Myself'}; @track message = 'Hello’; unbound = 'Hi’; changeHandler(event) { this.message =; } }
  20. 20. One-way binding We can also notice that the LWC counterpart contains a lot more Javascript code, including handler method which sets the value of attribute when the corresponding value on the UI is changed. Aura framework supports bound expressions and unbound expressions which are two-way binding and one-way binding while Lightning Web Components always use unbound or one-way binding expressions, so whenever the value is changed on UI, developer needs to write a handler to capture that and update the corresponding attribute value. In Lightning web components, the data binding for property values is one way. If the property value changes in the owner component, the updated value propagates to the child component. The reverse is not true.
  21. 21. Migrate Interfaces There are no interfaces for LWC. How can we migrate existing Aura Component Interfaces to Lightning Web Components? To migrate context availability interfaces set targets metadata property in configuration file. Salesforce documentation provides the following table to address this question. Interface Add to *.js-meta.xml: forceCommunity:availableForAllPageTypes <targets> <target>lightningCommunity__Page</target> </targets> flexipage:availableForAllPageTypes <targets> <target>lightning__AppPage</target> <target>lightning__RecordPage</target> <target>lightning__HomePage</target> </targets> flexipage:availableForRecordHome <targets> <target>lightning__RecordPage</target> </targets>
  22. 22. Migrate Interfaces There are no interfaces for LWC. How can we migrate existing Aura Component Interfaces to Lightning Web Components? To migrate interfaces providing context data properties import corresponding Javascript module Salesforce documentation provides the following table to address this question. Aura Component Interface Add to Javascript lightning:hasPageReference import { CurrentPageReference } from 'lightning/navigation'; @wire(CurrentPageReference) pageRef; force:hasRecordId import { LightningElement, api } from 'lwc'; @api recordId; force:hasSObjectName import { LightningElement, api } from 'lwc'; @api objectApiName;
  23. 23. Migrate References How can we migrate existing Aura Component references to Lightning Web Components? Aura framework uses camelCase style for references while LWC uses kebab-case style. HTML specification mandates that tags for custom elements aren’t self-closing. So to migrate the following code of AuraContainer component <aura:component> <c:AuraContained/> <lightning:formattedNumber value="5000" style="currency" currencyCode="USD" /> </aura:component> the following code inside your lwcContainer Lightning web component should be written <template> <c-lwc-contained></c-lwc-contained> <lightning-formatted-number value="5000" style="currency" currency-code="USD"> </lightning-formatted-number> </template>
  24. 24. Migrate Iterations How can we migrate existing Aura Component iterations to Lightning Web Components? Aura Iterations become HTML Iterations. Migrate <aura:iteration> tags in an Aura component to for:each directives in a Lightning web component’s HTML file. So, the following Aura component code part <aura:iteration items="{!}" var="property"> <c:PropertyTile property="{#property}"/> </aura:iteration> transforms to the following LWC counterpart <template for:each={properties} for:item="property"> <c-property-tile property={property} key={property.Id}></c-property-tile> </template>
  25. 25. Migrate Conditionals How can we migrate existing Aura Component references to Lightning Web Components? Migrate <aura:if> tags in an Aura component to if:true and if:false in a Lightning web component. So, the following Aura code <aura:if isTrue="{! > 1}"> can be transformed to the following LWC counterpart <template if:false={isFirstPage}> In html file and @api pageNumber; get isFirstPage() { return this.pageNumber === 1; } in Javascript file. Moving business logic determining condition for being on the first page to the Javascript allows developers to write unit tests for it.
  26. 26. Migrate Initializers How can we migrate existing Aura Component initializers to Lightning Web Components? Aura Initializers become lifecycle hooks. Replace an init event handler in an Aura component with the standard JavaScript connectedCallback() method in a Lightning web component. So the following code <aura:handler name="init" value="{!this}" action="{!c.onInit}" /> can be translated into such code inside the Javascript file connectedCallback() { // initialize component }
  27. 27. Migrate CSS How can we migrate existing Aura Component CSS to Lightning Web Components? To migrate CSS just proprietary THIS class, that Aura components use, should be removed. This Aura CSS code snippet .THIS .lower-third > p { padding: 0; } corresponds to the following LWC CSS code snippet counterpart .lower-third > p { padding: 0; }
  28. 28. Shadow DOM
  29. 29. Shadow DOM CSS Aura component styles cascade to any Lightning web components that they contain. However, the styles of a Lightning web component never interfere with other Lightning web components or with Aura components. Lightning web component styles don’t cascade to their children. Overriding styles that you don’t own can create many problems, so Lightning web components don’t allow it. Lightning web components use a web-standard mechanism called shadow DOM that hides the elements inside the component from the page that contains the component. Because Lightning web components have a shadow DOM, styles defined in a component’s style sheet are scoped to the component. They don’t apply to parent, child, or sibling components. This rule is strict, but it allows a component to be reused in different contexts without losing its styling. It also prevents a component’s styles from overriding styles in other parts of a page. To make development easier for component authors, a Lightning web component’s shadow DOM works a bit differently than the web standard. One difference is that the shadow DOM for a Lightning web component is created automatically. The component author doesn’t have to implement it. Also, a Lightning web component’s shadow DOM works even on browsers that don’t natively support shadow DOM.
  30. 30. JS Code Reuse In Aura framework the only way to reuse Javascript Code was creation of abstract basic component and inheritance of it by descendants components. If a component needs to reuse code from two different components, one of those aura components should inherited another since multiple inheritance is not allowed in Aura framework. Lightning Web Component Javascript Module can however import as many other modules as developers want. Also, Javascript code from Lightning Web Component can be reused in Aura component as well. In LWC developer needs to import the module to use methods from it while in Aura Component the module should be included in markup and then retrieved in Javascript code. So LWC to Aura Javascript code reuse is implemented through aggregation instead of inheritance
  31. 31. LWC JS Code Reuse /*utils.js*/ export function isFunction(value) { return typeof value === 'function'; } /* libcaller.js */ import { LightningElement, track } from 'lwc'; import { isFunction } from 'c/utils'; export default class LibCaller extends LightningElement { @track result; checkType() { // Call the imported library function this.result = isFunction( function() { console.log('I am a function'); } ); } }
  32. 32. Aura JS Code Reuse <aura:component> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <p>Aura component calling the utils lib</p> <!-- add the lib component --> <c:utils aura:id="utils" /> </aura:component> ({ doInit: function(cmp) { // Call the lib here var libCmp = cmp.find('utils'); var result = libCmp.isFunction( function() { console.log(" I am a function"); } ); console.log("Is it a function?: " + result); } })
  33. 33. Third-party libraries For third-party Javascript libraries stored in static resources, global value provider was used with ltng:require tag like following <ltng:require scripts="{!$Resource.resourceName}" afterScriptsLoaded="{!c.afterScriptsLoaded}" /> In LWC static resource is imported through import command import resourceName from '@salesforce/resourceUrl/resourceName'; and then loadScript or loadStyle methods can be used to load the third-party library.
  34. 34. No Dynamic Create There is no equivalent for dynamic components creation $A.createComponent() method from Aura framework in LWC implementation. Salesforce decided deliberately not to provide dynamic components creation equivalent since they believe that this feature has led to buggy and convoluted code existence in Aura components and they decided not to provide this feature in LWC to avoid buggy and convoluted code. However, inside Aura component or app dynamic component creation can be used to create LWC component dynamically inside an Aura component.
  35. 35. Apex Calls in LWC There is one standard way to call Apex method from Aura framework While in LWC there are three different ways how Apex can be used. To call an Apex method, a Lightning web component can: Wire a property Wire a function Call a method imperatively In every way apex method should be imported first by using syntax import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodRef’; Any Apex method to be exposed to LWC component, should be declared as static and public or global method with @auraEnabled annotation. The first two options require Apex method to be cacheable, which means it should be declared with @AuraEnabled(cacheable=true) annotation while imperative Apex call can be used even if Apex method is not cacheable. public with sharing class ContactController { @AuraEnabled(cacheable=true) public static List<Contact> getContactList() { return [SELECT Id, Name FROM Contact LIMIT 10]; } }
  36. 36. Wired property The simplest way to call Apex from LWC is to use wired property. import { LightningElement, wire } from 'lwc’; import getContactList from '@salesforce/apex/ContactController.getContactList’; export default class ApexWireMethod extends LightningElement { @wire(getContactList) contacts; } In the code snippet above contacts is a property and it is wired to Apex method by @wire(getContactList) decorator. The following markup displays the data retrieved by Apex <template if:true={}> <template for:each={} for:item="contact"> <p key={contact.Id}>{contact.Name}</p> </template> </template> <template if:true={contacts.error}> <c-error-panel errors={contacts.error}></c-error-panel> </template>
  37. 37. Wired function Let’s consider example when Apex method is wired to a function. @track contacts; @track error; @wire(getContactList) wiredContacts({ error, data }) { if (data) { this.contacts = data; this.error = undefined; } else if (error) { this.error = error; this.contacts = undefined; } } Here wiredContacts is a function and it is wired to the same Apex method.
  38. 38. Wired function HTML The markup to display the data is similar but different <template if:true={contacts}> <template for:each={contacts} for:item="contact"> <p key={contact.Id}>{contact.Name}</p> </template> </template> <template if:true={error}> <c-error-panel errors={error}></c-error-panel> </template> It is possible to pass parameters to Apex from in property or function declaration import apexMethod from '@salesforce/apex/Namespace.Classname.apexMethod'; @wire(apexMethod, { apexMethodParams }) propertyOrFunction;
  39. 39. Imperative Apex call If an Apex method is not annotated with cacheable=true the only option to call it in LWC is imperative Apex call. Since cacheable methods cannot perform DML operation, when DML is needed, the only way to call such method from LWC is Imperative Apex approach. @track contacts; @track error; connectedCallback() { getContactList() .then(result => { this.contacts = result; }) .catch(error => { this.error = error; }); } The markup to display the data can be the same as for wired function approach
  40. 40. Migrate Facets Aura framework provided facets options to dynamically insert component markup using attribute with type of Aura.Component[]. For example, the following code could be used: <aura:component> <aura:attribute name="header" type="Aura.Component[]"/> <div> <span>{!v.header}</span><br/> <span>{!v.body}</span> </div> </aura:component> In Lightning web components, slots are used instead of the facets. To migrate body facet, it is possible to use unnamed slot and for header it is possible to use named slot like following <template> <div> <slot name="header"></slot><br/> <slot></slot> </div> </template>
  41. 41. Populate slots To use this component in parent, markup should be provided for slots in the following way <template>    <c-named-slots>        <span slot="header">Header !</span>        <span>Body content</span>    </c-named-slots> </template> In this example, “Header !” text is passed to the header slot and span with content “Body content” is passed to unnamed slot. If a component has more than one unnamed slot, the markup passed into the body of the component is inserted into all the unnamed slots. However, such UI pattern is unusual. A component usually has zero or one unnamed slot.
  42. 42. Migrate Global VP Many Global value Providers in Lightning have corresponding @salesforce Javascript module in LWC. globalId Not available $Browser Not available $ContentAsset @salesforce/contentAssetUrl $Label @salesforce/label $Locale @salesforce/i18n $Resource @salesforce/resourceUrl For more details, visit documentation
  43. 43. Migrate Events Instead of the proprietary Event object in Aura components, the Event or CustomEvent standard DOM interfaces should be used. CustomEvent is recommended to use. There’s no equivalent in Lightning web components for the <aura:registerEvent> tag in Aura component markup to register that a component can fire an event. To fire an event, Instead of syntax of Aura framework,  standard DOM method this.dispatchEvent(myEvent) should be used in Lightning web components. This is an example of code which fires an event in LWC export default class PropertyTile extends LightningElement {   @api property;   propertySelected() {       const selectedEvent = new CustomEvent('selected', {           detail:,       });       this.dispatchEvent(selectedEvent);   } }
  44. 44. Migrate Handlers Instead of the proprietary Event object in Aura components, the Event or CustomEvent standard DOM interfaces should be used. CustomEvent is recommended to use. Also there's no equivalent in Lightning web components for the <aura:handler> tag in Aura component markup that configures an event handler. Lightning Web Components can have declarative handlers declared similar to Aura components, the only major difference here is that event name in LWC is prefixed by “on” <c:child notification="{!c.handleNotification}"/> Note the difference in markup. <c-child onnotification={handleNotification}></c-child>
  45. 45. Communication To communicate between components outside of the same DOM tree, copy library from Salesforce sample repositories for pubsub module implementation. In a publish-subscribe pattern, one component publishes an event. Other components subscribe to receive and handle the event. Every component that subscribes to the event receives the event. For example, if two components are added to a Lightning page in Lightning App Builder, the pubsub module should be used to send events between them. The pubsub module exports three methods. register : Registers a callback for an event. unregister:  Unregisters a callback for an event. fire : Fires an event to listeners.
  46. 46. Fire in LWC to Aura This is an example how an event can be fired from LWC and received in Aura component. LWC Catch And Release component code listing import { LightningElement } from 'lwc’; export default class CatchAndRelease extends LightningElement {    /**     * Handler for 'Fire My Toast' button.     * @param {Event} evt click event.     */    handleFireMyToast(evt) {        const eventName = 'notification’;        const event = new CustomEvent(eventName, {            detail: { message: 'See you on the other side.’ }        });        this.dispatchEvent(event);    } }
  47. 47. Catch in Aura This is an example how an event can be fired from LWC and received in Aura component. Aura Catch and Release Wrapper component code listing <aura:component implements="force:appHostable">    <c:catchAndRelease onnotification="{!c.handleCustomEvent}"/> </aura:component> ({    handleCustomEvent: function(cmp, evt) {        // Get details from the DOM event fired by the Lightning web component        var msg = evt.getParam('message') || '';    } })
  48. 48. Testing Lightning In Aura components, Lightning Testing Service can be used to test components. In Lightning web components, Jest can be used for unit testing. If Jest doesn’t cover all your test cases, use Lightning Testing Service to cover the remaining test cases. Jest unit tests can be stored in the same source code repository but they cannot be saved to cloud and can only be run locally or by continuous integration server machine.
  49. 49. Aura Methods Aura methods can become Javascript methods. Migrate methods from <aura:method> tags in an Aura component to JavaScript methods with an @api decorator in a Lightning web component.
  50. 50. More topics… Import Objects and Fields from @salesforce/schema (object and fields references instead of string literal) Refresh the Cache (cacheable methods update) JavaScript Property Names (Don’t start names with on, aria, data, don’t use slot, part, is as names) Library component mapping (most lightning: library components are supported, for complete list visit link) Standard event mapping (use lifecycle hooks for valueInit, valueDestroy and valueRender,use hashChange instead of aura:locationChange, use navigation service and pageReference object for force:navigate… or lightning:openFiles or force:createRecord or force:editRecord; import ShowToastEvent from the lightning/platformShowToastEvent module instead of force:showToast, for complete list visit link)
  51. 51. Even more topics… Navigation mixin Page reference types Event best practices Salesforce modules
  52. 52. Conclusion As we can conclude now, Salesforce provide Lightning Web Components to be able to follow the latest Javascript code standards and to discourage developers to use some features of Aura framework which might lead to buggy and convoluted code. Also UI performance can be significantly increased on modern browsers which support the latest Javascript code standards. Polyfills to older browsers which do not support the latest code standards are also provided but they can slow down performance on older browsers. Every Salesforce developer should learn the new features provided by Salesforce to suggest the customers the best appropriate development option.
  53. 53. References1. 2. 3. 4. 5. 6.