Firebase uses a lot of internal asynchronous calls that trigger change detection because of Angular/Zone monkey-patching websockets and setInterval
etc. Even when I'm not interacting with my app, I see a cascade of change detection happening all the time, which contributes to slowing things down especially on mobile.
This default behavior could be useful, but the way I'm using Firebase right now I have pretty tight control over when I need to update the view, so callbacks from Firebase are used in such a way that change detection will happen manually anyway.
I know setting change detector strategy to OnPush
will help here, which I'm working on, but I want to attack this from every angle.
I'm familiar with zone's runOutsideAngular
but not sure now to apply it here since all of the async calls are happening inside the Firebase module.
How can I get Firebase to do all its business outside the angular zone?
Edit: Example code that shows the problem:
import {Component} from '@angular/core';
@Component({
selector: 'test-component',
template: 'hello world'
})
export class TestComponent {
ref: Firebase;
constructor() {
this.ref = new Firebase('<firebase URL>');
}
ngDoCheck() {
console.log('Check the stack - this is being called continually via async functions used internally by Firebase.');
debugger;
}
}
This is obvious in retrospect, but simply instantiating the Firebase reference outside of the zone did the trick. E.g.:
By putting breakpoints in
ngDoCheck
in my components I was able to trace all the change detection cycles back to that line where I instantiate the Firebase reference, which hinted that running it outside the zone would prevent them.Note that if you go this route you have to make sure to change detection is getting triggered when necessary. See https://stackoverflow.com/a/34829089/458614 for examples.