Angular/AngularJS Upgrade app unresponsive when browser tab in background
Asked Answered
E

3

23

I have an Angular/AngularJS Upgrade App and am currently in the process of migrating everything from AngularJS to Angular. It's a fairly large project so I definitely need to go the Upgrade way.

I use the @uirouter/angular-hybrid and have a root state that is still AngularJS (Navigation and stuff) and a child view. In this child view, I'm now slowly upgrading all components to Angular. For performance reasons, I had to use the downgradeModule() (https://angular.io/guide/upgrade-performance) instead of the UpgradeModule.

For UI components I use Angular Material 2.

So much for the setup, now to the question/problem:

When the tab with the page is in the background and you come back to the page later (at least 5 to 10minutes) the entire page lags and is unresponsive. The longer you are away and the tab is in the background, the longer the lag is.

What I already tried/found out:

  • There seem to be events registered but since the tab is in the background they are not executed but are all executed at the same time once you go back to the tab. Here's a screenshot of the profiling profiling screenshot
  • Removing Angular change detection and using ngZone: 'noop' has no effect
  • Disabling all Animations has no effect
  • Enabling Angular production mode improved it a little bit (could also be an illusion) but the problem still persists
  • I develop in Chrome, the problem exists in other Browsers (e.g. Firefox, Safari) as well
  • Only happens if the router view component is an Angular component, AngularJS view component seem to be not affected

I'm currently working on a clean sample app to reproduce the problem and have some more context for further test. I will add it soon.

Lib versions

Angular: 6.1.0

AngularJS: 1.7.2

zone.js: 0.8.26

@uirouter/angular-hybrid: 6.0.0

Update (Aug 2019)

Still happening with current Lib Versions Angular 8, AngularJS 1.7.8 & uirouter/hybrid 8

Ezar answered 27/7, 2018 at 14:30 Comment(2)
Are the background events important? What kind of events are they?Mojave
I don't really know. Those events seem to be fired from angularEzar
C
1

Try utilizing this implementation pattern on all ng2 components.

https://angular.io/api/core/ChangeDetectorRef#detach-change-detector-to-limit-how-often-check-occurs

The concept is that it would remove the component from having it's updates or rendering done by angularjs.

From the Documentation:

class DataListProvider {
  // in a real application the returned data will be different every time
  get data() { return [1, 2, 3, 4, 5]; }
}

@Component({
  selector: 'giant-list',
  template: `
      <li *ngFor="let d of dataProvider.data">Data {{d}}</li>
    `,
})
class GiantList {
  constructor(private ref: ChangeDetectorRef, private dataProvider: DataListProvider) {
    ref.detach();
    setInterval(() => { this.ref.detectChanges(); }, 5000);
  }
}

@Component({
  selector: 'app',
  providers: [DataListProvider],
  template: `
      <giant-list><giant-list>
    `,
})
class App {
}

You're going to detach() the component essentially and then manually detect changes.

Centiare answered 6/8, 2018 at 22:38 Comment(3)
thanks for you answer. will try to try this. not quite sure yet how to detect changes without an intervalEzar
you want me to detach the parent page component or all components used on this page? just tried it with the page component itself and no difference. @CentiareEzar
Still working on getting a more refined root level answer working.Centiare
C
0

Try disposing of the service on each tab load, then creating new events to listen for new changes.

Also, this may work, but is a workaround considering the README @ https://github.com/ui-router/angular-hybrid#limitations

This section of the README may suggest that downgrading isn't a seamless option:

Limitations:

We currently support routing either Angular (2+) or AngularJS (1.x) components into an AngularJS (1.x) ui-view. However, we do not support routing AngularJS (1.x) components into an Angular (2+) ui-view.

If you create an Angular (2+) ui-view, then any nested ui-view must also be Angular (2+).

Because of this, apps should be migrated starting from leaf states/views and work up towards the root state/view.

Centiare answered 4/8, 2018 at 0:14 Comment(8)
what do you mean by disposing of the service on each tab load? on what service? and as for the second part it does not really matter in our case. We strictly follow their guidelines. Angular JS Parent view and Angular 2+ child view. The routher throws a hard exception if you try it the other way aroundEzar
Try disposing of either depending on your application: ui-router.github.io/ng1/docs/latest/classes/… ui-router.github.io/ng2/docs/latest/classes/…Centiare
@NicolasGehlert I'm currently writing up a base test on this. You said "When the tab with the page is in the background...". This is a regular web browser tab, not a UI component of some sort with tabs for content?Centiare
@NicolasGehlert also, if it's a browser "tab", if you let the page ( as in have the page be the active viewed tab in the browser ) sit for while does it return to being responsive and working?Centiare
@NicolasGehlert Can you check what the results are of the following test: 1. refresh the page 2. blur the page, going to another tab for 30 or 60 seconds ( it may take longer to see lag ). 3. return to the tab, note the level of responsiveness 1-10, 1 being very slow, 10 being normal. 4. repeat the test increasing page blur time to 5min or 10min.Centiare
yes regular browser tab. yes if you let it sit for a while it will eventually be responsive again. my guess is once all accumulated events are processed. on very rare occasions the tab will die and can only be fixed with restarting the browser. will come back later with the test results. thanks for your workEzar
so everything <5 minutes is basically 9 or 10. You don't really feel a difference if you don't really pay attention. 5-15 min it goes down to 5 or 6. And then it gradually gets worse over time. @CentiareEzar
@NicolasGehlert Still working on a more root level solution.Centiare
S
0

Have you try looking into UrlHandlingStratery? We managed to use Angular on top of AngularJS stack and slowly re-write when necessary.

What we did was we use both Angular and AngularJS router, using UrlHandlingStrategy to determine which route is to be handled by Angular and if the route is not to be handled by Angular, it will then go to AngularJS route.

Without looking into your setup, I can only guess. Maybe because the route is going back and forth all the time that

Sacrarium answered 11/8, 2018 at 13:5 Comment(1)
Actually I did, but the problem is I have quite a complex setup with abstract states and I would need to duplicate it for both angular versions. So I’m kind of force to use the UI Router Hybrid. The state transitions are fine, there is no state ping pong. At least not to the outside, don’t know what they are doing under the hood but I’m strictly following there setup suggestions. Thanks for your answerEzar

© 2022 - 2024 — McMap. All rights reserved.