What can cause $A.createComponents to be slow?

Simple to ask, possible hard to answer. I have written a Lightning app to create forms which works a bit like the page builder in LEX itself. It saves the form description into JSON, and then dynamically creates all of the components from the JSON description upon load.

Since Winter 18, the performance has dropped dramatically. So, I want to know if there are some things that I should be taking into consideration when calling $A.createComponents and/or what is it actually doing that is taking all the time?

In my app, I’m calling $A.createComponents with 1,311 components in the array to create. That takes about 8s to run. Client caching is enabled and I’m using <aura:dependency> to declare every type I’m going to create.

One obvious change I could make is to break those 1,311 components up into chunks and load them progressively. Either at arbitrary limits, or by getting some components to load themselves e.g. create a tabbed section of the form on load, but let the tabbed section load its own children in another call to $A.createComponents once we have something on the screen. That’s going to be a fair amount of messing around and introduces the complexity of what to do when the user starts interacting with the form before it has all loaded. So, I’d rather not.

One thing I’ve already tried is trimming down the number of components inside the ones I’m creating e.g. by using $A.createComponents again inside the children instead of <aura:if> as suggested here: https://www.codescience.com/blog/2017/performance-tuning-for-lightning-components-with-large-volume-subcomponents That definitely reduced the number of components by the time it had fully loaded (as measured by $A.componentService.countComponents()), but hasn’t noticably reduced the load-time.

I’ve tried profiling with Lightning Inspector and Chrome Performance tab (on examples large and small), but a great chunk of the time is inside aura code, not mine, so that hasn’t really helped.

Answer

$A.createComponent() has a few side effects to be aware of and without knowing the structure of your application, its hard to give you advice on which direction to go.

$A.createComponent() will try to create an instance of whatever component you requested. If it has all the code for that component already on the client, it’ll go and do that right away. If it doesn’t have all the code, it needs to go to the server for the code. Also it doesn’t just get that one component, but all of its dependencies as well, since it’ll need those to work.

This can result in a lot of code being downloaded.

Now when you say you’re creating 1311 different components, that is a lot. Each component you create is probably extending from aura:component, so you’re at least creating 2622 components, and then each of those are creating components. You could be creating 10k or 20k component instances, which is just a lot of work for the framework to do.

There is nothing you can do to make a high component count faster. Its just expensive to do. Now when considering lowering your component count I’d offer the following options.

  • Re-architect
  • Use the same techniques you would for creating 20k dom elements, progressively load.
  • Use the new Lightning Web Components framework. Lightning Web Components are cheaper to create, just don’t create them all through $A.createComponent(). Create one LWC component which has all 1311 components inside it.
  • If the $A.createComponent() call goes to the server, limit its dependencies.
  • Move aura:if and aura:iteration component usages in markup files to code. (These two usages in markup files are actually components and have a lot of overhead)

Hope that helps.

Attribution
Source : Link , Question Author : Aidan , Answer Author : Kris Gray

Leave a Comment