-
-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance issues with app-sidebar-nav components due to ngClass bindings #74
Comments
Related issues in the Angular repo: |
Hi @coyoteecd PR welcome! |
We're currently testing the use of custom pipes instead of helper functions in templates for badge/icon classes. Seems promising. |
@coyoteecd |
@xidedix The pipe fix works fine. There is still one left-over however, you'd need to include it here as well: Lines 11 to 13 in bd5fd37
|
@coyoteecd done - please update to 2.5.5 |
OS: Windows 10
Browsers: Chrome 75.0.3770.142 64-bit, Firefox 68.0.1
Angular 7.2.12
After upgrading to CoreUI 2.4.5 from an old v1.x version, I am experiencing significant performance issues across our entire app. The observed behavior is that typing fast in a text input is laggy; keeping a key pressed shows noticeable hiccups every 5 to 10 characters. All in all, it just gives the feeling of bad UX.
When profiling with Chrome, I noticed that a good deal of time is spent in a "Recalculate Style" step:
Switching to Event Log tab in Chrome Debugger while running on a debug version of our app, I noticed that every keypress event triggers a style recalculation. One can find the source of style changes by clicking Reveal link:
.
Source is AppSidebarNavLinkComponent; our app has 20+ sidebar link items and on every keypress, all of them schedule a style recalculation by removing and re-adding the same CSS classes:
Looking at the code, I believe the root cause is the refactoring done in this commit, as well as this older commit. Before those changes, the ngClass was bound to an inline expression, and it was converted to function calls e.g. getLinkClass or helper.getBadgeClass(item). All of these functions always return a new object reference when called, which makes Angular think - during every change detection cycle - that the ngClass attribute has changed. It then proceeds to remove all classes and re-add them back, even if the object structure is the same; verified this by debugging.
A possible solution is to maintain string arrays in each nav item component, and have the getLinkClass/getBadgeClass etc. functions return the same array instance every time is called. NgClass directive has an IterableDiffer to detect changes in the array elements, so clearing the array and re-adding the same items all over again should be okay as long as we keep the same array reference. I verified this and it does get rid of the Recalculate Style, solving the issue.
For example, in app-sidebar-nav-link.component.ts:
becomes:
You would also have to add array variables for badge/icon classes as well, and change SidebarNavHelper to return an array of class names, for the HTML to bind to:
It kinda breaks the
SidebarNavHelper
idea and results in more code; other alternatives might be to introduce an inheritance tree for the app-sidebar-nav-xxx.component classes or to change the SidebarNavHelper to receive the classes array as input.Let me know what you think. I am willing to fork and submit a pull request if the above changes look acceptable.
The text was updated successfully, but these errors were encountered: