19

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.

  • Most like the slowness you see is rendering time. Can you break down the 1311 grouped by type, e.g. 511 x ui:inputText, 77 x lightning:inputField and so on? did you try to measure times of creating 1000 compos of one type vs. 1000 compos of another type? I'm pretty sure you will find differences. I found picklists with lots of options to be super slow. – Uwe Heim Oct 27 '17 at 9:48
  • If you use the jquery library, try removing that. Aura doesn't seem to play nice with other JS frameworks. – SFAaron Jan 7 '19 at 20:37
4

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

| improve this answer | |
  • Thanks Kris - New releases have actually improved things a lot since I first posted the question. One thing I tried (which seems to work) is to move some work from the init() method of the component into another method (e.g. to do things that might be done with aura:if), then enqueue it with $A.enqueueAction(). Does that sound like a good/bad idea to you? – Aidan Jan 7 '19 at 9:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.