I'm using AngularJS 1.0.8.
The problem: I have a dynamic website that can be built from various components, or widgets: paragraphs, text blocks, images, hyperlinks, and tables, for that matter. A paragraph is a container of more components. A table is also a kind of a container - it can hold other components, and it arranges them as a datagrid.
The website is not static, i.e. I don't have a pre-defined layout of such components. Instead, I get a JSON in startup, that specifies the layout of the components.
Originally, I had a directive of each such component, using templates for that directives, and occasionally using $compile to change the DOM a bit for more complex components. For the 'container' components - paragraphs and tables - I used ngRepeat to render all of the components that are contained in that container-component.
That was problematic performance-wise. It would take the website many seconds to load on Chrome/Firefox, with the time spent mainly in the AngularJS render mechanism (not in IO, I figured).
So I decided to change the directives of these components. Instead of using ngRepeat, which is not really necessary since I don't need the two-way binding (the content in the website is not interactive and cannot be changed, so really I only need to render it once, very much like a servlet) - I built the HTML string in the directive myself, using plain JS, iterating over all of the contained components that exist in the model, and at the end I $compiled and linked it.
The result wasn't good enough again. For a table of a few hundered cells, it took ~500 milis to link in modern Chrome/Firefox, and ~4000 milis in IE9, and ~15000 milis in IE8, and IE7 is still rendering so I can't give you the time :)
I thought that the problem might be with an extensive use of directives.
A simple:
<div my-table-component data="data"></div>
element would result, after the link, in a <table>
tag with 30-40 <tr>
tags, each with 10 <td>
tags, and in each there would be an additional <div my-text-component>
or <div my-image-component>
that would then have to be compiled and linked by itself (since it has a directive).
I though that since my website is not interactive to begin with, I don't really need this. Maybe I could avoid using directives for each component, and leave only a directive for the container-components. In these directives, I would create the actual HTML template of every possible other component, instead of using directives that would do that.
That takes me another step away from the AngularJS idea towards a servlet idea. And it kind of sucks. So maybe one of you can offer a better approach for me... Maybe the performance problem is not even there? Maybe a use of directives (and hopefully ngRepeat) can be fine performance-wise even with this amount of items? Maybe there's a better way to make an insightful performance benchmark, other than using Chrome's Developer Tools, Firebug, and Chrome's Batarang AngularJS extension (none of them really directed me in a productive way).
Using a lot of nested directives by itself is not a problem, but any extensive binding could have huge impacts.
If someone is still looking for an aswer to this, using Angular 1.3+, OP could solve his problem by first using one-time binding on all the elements on which he says there is "no need for two-ways bindings", using the ::binding
syntax.
In addition, I would suggest trying to spot which bindings exactly are being particularly slow, using the amazing profiling snippets from this website: http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html
Finally, what often takes most time in Angular, especially while building big ng-repeated tables, is the compilation phase. So if possible try to only build a restricted number of elements (using limitTo
) and then load more as the user scrolls for instance. Many directives address this concern (look for "infinite scrolling")
All in all, I think it is still worth trying to optimize an Angular application rather tham switching to native JS, most of the time the lag comes from a developper mistake: some applications have thousands of watchers and run pretty smoothly (*cough* like mine *cough*).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With