[SalesForce] Effectively profile & speed up slow Lightning components (using Chrome Lightning Inspector)

Note: 5 years ago I asked the same about Visualforce here and it helped to collect a lot of knowledge. So let me try this again for Lightning.

I am currently working on a quite complex Lightning page where users can edit many records at once in a editing grid based on the Data Grid component from Apphiphony's Strike component library.

Even when incorporating a spinner the page loads deadly slow and there are plenty of reasons why:

  • Multiple Apex callouts using Promises (just takes a few seconds)
  • Complex JSON from Apex is passed into the grid component
  • Grid component dynamically creates 1000+ components (e.g. cell editors)

I do that not because I don't know that these things harm performance in general but because I have to and or didn't find a solution in common speed-up techniques like pagination, lazy loading, static creations of components,..

Ok, here is my question:

  1. How can I use the Chrome Lightning Inspector to pinpoint the worst bottlenecks?
  2. What are the most common problems that I should look for and how to fix them?

enter image description here

Best Answer

Client Side Performance Consideration

The Chrome lightning debugger has a tree view for the performance thats better than chart view and i find it easier to debug performance bottle necks .

Lets take a look at the screenshot below

enter image description here

Looks like the strike_row component is the bottle neck due to multiple aura:if statements .

The performance really is hit by below lines

<aura:iteration items="{!v.fields}" var="field" indexVar="index">
        <td data-label="{!field.label}">
            <div aura:id="value-output" class="{!if(field.dataType != 'COMPONENT', 'slds-truncate', '')}" title="{!if(field.dataType == 'COMPONENT', '', field.value)}">
                <aura:if isTrue="{!field.dataType == 'BOOLEAN'}">
                    <ui:outputCheckbox value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'CURRENCY'}">
                    <ui:outputCurrency value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'DATE'}">
                    <ui:outputDate format="M/dd/yyyy" value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'DATETIME'}">
                    <ui:outputDateTime format="M/dd/yyyy H:mm a" value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'EMAIL'}">
                    <ui:outputEmail value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'NUMBER'}">
                    <ui:outputNumber value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'PHONE'}">
                    <ui:outputPhone value="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'URL'}">
                    <ui:outputURL value="{!field.value}" label="{!field.value}"/>
                </aura:if>
                <aura:if isTrue="{!field.dataType == 'STRING'}">
                    {!field.value}
                </aura:if>
            </div>
        </td>
    </aura:iteration>
</tr>

aura:iterations with multiple if statements ,clearly there is a rendering cost .

How Would we else solve dynamic display of field based on data type ?

The answer to this is use $A.createComponents() .This will bring the number of components to less than before .

Also two way data binding has its own cost associated to it .Only way to avoid two way data binding would be just use jquery or plain old javascript and build your own logic in lightning container .

Here is a handy blogpost that might explain you some of the approaches .

Server Side Performance Consideration

On Server side there are few techniques that has found to consume less time

  1. JSON stringify the result from @AuraEnabled method and parse on client side in controller js to Javascript Objects .This is efficient than using a message layer class
  2. Use Static variables to cache repeating logic so that you do not fetch the same data again and again
  3. Use continuation class to make multiple calls in parallel .There is already a sample application to observe how one can iframe a 1px vf frame and get data via remoting .

Framework Specific Optimization

Use Storable actions along with aura enabled methods .Here is a handy article on this .

Adopt Lightning Base Components

I would recommend looking to see lighnting:datatable to see if this solves your needs .If not would recommend building one of your own with performance considerations .

Related Topic