Angular 1.6 many instances of the same component on a page - javascript

I have a component inside an ng-repeat, and sometimes it creates a really big number of components (over 1000), causing a significant delay (several seconds) on page load. Profiler shows that all code that causes noticeable delay is executed inside angular or angular-select (which is used by my custom component), so it's not related to my code, although it might be related to some watches that I'm setting.
What is the common way of dealing with this? Is it possible to initialize a component only once and create multiple instances without calling the same code thousands of times?

Usually a component cannot be initialized once and cloned. It would be possible for purely static component, but compilation wouldn't be a bottleneck for this case.
When there's a significant number of component/directive instances that should be necessarily displayed simultaneously, they have to be modified to not use data binding if possible, or use one-time watchers. This way watchers count stays within a desirable limit (usually ~1000 watchers).
Custom solutions can be used instead of ng-repeat for performance boost. And 1000 components preferably shouldn't be displayed at once.
There are several infinite scroll solutions for Angular that limit the items to the ones that are shown in visible area.

Related

How to measure a large number of components in React Native without causing an error?

I'm trying to implement a generic Drag-and-Drop module that I may or may not release on NPM.
I took inspiration from an already existing DnD module which consisted of essentially two main components: Draggables and DropZones.
The Draggable components would enable any content that they enclosed to be dragged around, and DropZones were the components that would react to when a Draggable component was dragged in/out of them and/or dropped onto them.
The module's functionality was too basic for what I needed, so I set off on making my own.
Everything has been going fine except for one aspect: measuring the absolute position of a large number of components in order to find their corresponding bounding shapes for collision detection.
Currently, I've been using the View's measure method to measure the absolute position and size of my components, however, if you call this method too many times within a short period of time, React Native will throw this error: Warning: Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code and it lists the offending method as {"module":"UIManager","method":"measure"}.
If I make a basic for loop that repeatedly calls the measure method, I can get it up to just over 500 iterations before React Native complains (this number may be hardware-dependent; I'm not sure).
Also, the same problem happens when using the View's other measuring methods (e.g. measureInWindow, measureLayout).
What's even worse is that up until now, I have been calling the measure method in a View's onLayout callback, however, I recently discovered that onLayout does not get called when a style changes that doesn't directly affect the given View (such as when a parent component's margin changes).
This means that the given components can be re-positioned (relative to the screen) without them knowing about it.
Because of this I will have to use a different means of notifying my components that they need to remeasure themselves.
I thought about using some of the life-cycle methods that pertain to component updates, but that would most likely be even worse, because most of them get called every time the component updates which is far more often than a layout happens.
Edit: One other problem with using the life-cycle methods that pertain to component updates is if a parent component prevents it's child components from being updated (such as through shouldComponentUpdate).

Preferred way of swapping big trees (e.g. pages in SPAs): `display: none`, `replaceChild()`, etc

When developing complex web applications, like SPAs, we are faced with the problem of displaying/enabling/keeping updated different parts of the application at different times.
For instance, as a simple example, consider swapping the current page/section/activity of the application in a SPA.
Assuming that these trees are non-trivial (they are entire pages, they may contain CSS animations, event handlers, some non-static content, etc.) and that we care about performance, what is, nowadays, the preferred way of swapping them in and out? What approach modern frameworks choose? Why?
In particular, several metrics are important to consider:
Overall performance/memory usage/etc. (i.e. when not swapping pages)
Actual time required to switch pages
Note that in order to be as quick as possible, we want to keep the content/pages pre-loaded somehow (i.e. no network requests are discussed here).
For context, here are several ways people have used over the years:
Have some string templates in JS. When pages are switched, replace entirely the contents with innerHTML at once (for performance), reattaching handlers and start updating the non-static values as needed at that moment, etc.
Keeping everything in the DOM (i.e. all elements of all possible pages), but have inactive pages with display: none. Then, swap the current page simply switching display property in the page going out and the one going in. Also, do not update non-visible pages to avoid performance penalties.
Keeping the trees in JS (i.e. keep a reference to each top-most Node of each page in JS), and swap them in and out of the DOM with e.g. replaceChild().

Angular 4 - it is more expensive to handle styles of a generic component or work with specific components

I'm working on a hybrid application for which I need a toolbar. This toolbar must handle different forms and functionalities, in some cases contains a title, other buttons and links and in others an autocomplete, then my questions is if is more efficient to build a dynamic component that accepts all these elements or work on different toolbar's that will be inserted and removed from the DOM as needed.
Thanks!
A dynamic toolbar will be faster, because angular wont need to re-render the whole toolbar each time it changes. It's smart enough just to find the stuff it needs to update.
Also it will make your code easier to maintain I think. Having multiple toolbars, probably with some shared logic/elements will cause repeated code.
Also you will probably have less lines of code with a dynamic toolbar, perhaps slightly reducing the size of your project. I suspect that wont be significant. Honestly, I think the biggest advantage wont be speed but cleaner, more maintainable code in general.
It depends on whether you are using lazy loading or bundling your entire App in one main.bundle.js
In the first case, you want to ship the strict minimum to the browser as it's needed. Therefore, you want separate component for each use case.
In the second case, it makes your app lighter to create on single component to handle different toolbar use cases.
To demonstrate this, (assuming you're not using lazy loading) you can create a small project with a main component which uses 2 different views.
In one case you create a single component for each view.
In the other you combine both views in one component.
Then build and serve both and you can see the difference in the weight of your JS files.
Hope this helps

How to optimize the rendering of components in Ember JS

There are around 3 hundred components rendered inside the wrapper component and its taking to much of time to render. But I need thousand of components to get rendered inside the wrapper container. How can I achieve this without any performance issues while rendering the components
Image shows the rendering time taken by 300 components which is too much
If you have a scroll and all of your components are not in the viewport at the same time, you may use the Proxy Pattern.
There is an ember addon called ember-in-viewport to detect whether your component is in viewport or not. By using it, you may implement the proxy pattern.
Here is a sample twiddle. At the application.hbs, if you use my-proxy-component instead of my-component, page rendering would be nearly 3 times faster.
These tips are kinda hacky but might help:
You might want to lazy load some of the components, like for example load the most critical ones and then load the rest changing a computed property after a fixed timeout on didRender event (during the idle state).
For example:
onDidRender: Ember.on('didRender', function() {
Ember.run.later(() => {
this.set('displayLazyItems', true);
}, 2000);
})
Another thing you might want to do is inline code instead of creating a new component for small items. Rendering those might take some serious time.
Record a timeline and ensure that the performance is actually coming from render time, sometimes is actually some javascript execution or loading that is messing up.
Lastly, ember 2.10 includes glimmer 2, this new render engine can optimize render time up to 50%, you might want to consider using it.

VirtualScroll rowRenderer method is called many times while scrolling

I have a react-virtualized's infinite scroll list, (Most of the setup is copied from this example). I'm providing it with a rowRenderer function like the specs requires. this works fine if the rowRenderer function is very lightweight (i.e returns a very basic component as row).
but the rendering of my RowComponent includes some Array.map over some properties. this shouldn't cause any problem except that the rowRenderer functions is being called tens or even hundreds of times while scrolling. this causes a performance issue, making the scroll not smooth enough.
So far I tried:
Caching my rowRenderer this works, but I don't like this solution as it may cause problems in the future.
Make my RowComponent's render function pure and implement shouldComponentUpdate using react-addons-shallow-compare. this slightly improved the performance but not enough.
In this example, the rowRenderer function is also being called many times per scroll (no perf issues there as the function is very lightweight), which makes me believe this behavior is by design. so:
Is caching a good solution? any advice in how to sync it with my app's state (I use redux for state management)? is there something I missed in the docs that can reduce calls to rowRenderer (there's no reason for my rows to change while scrolling)?
Author of react-virtualized here.
Your rowRenderer methods should be lightweight because, as you've found, they may be called rapidly when a user is scrolling. The good news is that- since browsers manage scrolling in a separate thread from the UI, this usually doesn't cause any performance problems. If anything, you may notice some empty/white space at the edge of the list in the direction you're scrolling- indicating that your renderers aren't able to keep up with the user's scrolling speed.
One caveat to be aware of though is that if you attach touch or wheel event handlers to a react-virtualized component or one of its DOM ancestors, this will force the browser to scroll in the main/UI thread. That can definitely cause slowness.
I'm currently in the middle of a major update (version 7) which, among other things, will passed named arguments to user-functions like rowRenderer. This will enable me to pass meta information (like whether or not the list is currently scrolling) which could enable you to defer "heavy" logic while a scroll is in progress. Unfortunately this isn't possible in version 6 unless you're willing to use a timeout as doron-zavelevsky mentions.
Edit: You may be happy to learn that with this commit cell caching has made its way into the upcoming version 7 release.
From my experience with this library (I'm not using the latest version though) - this is by design.
It makes sense - in order to avoid rendering all the list at once - and to allow you infinite scroll - it asks you every time to render the currently viewed item.
Your goal is to optimize the render function - as you yourself mentioned.
One more thing that can improve your overall experience is to check and see if your item contains some complex code in its componentDidMount life-cycle method - or any other code that runs post-render. If that's the case - you can optimize for fast scrolling by delaying these calculations with a timeout - and only let them run if the component is still mounted when the timeout passes.
Consider the case that you fast scroll over items to get to the bottom - there's no sense in fully populating all the items you scroll past on the way there. So you return the render result as fast as you can - and inside the item you wait ~200ms - and then you check whether the component is still mounted and do the real work.
Since isMounted is obsolete you can simply set a variable to true during componentDidMount and back to false of componentWillUnmount.

Categories