perf(angular): skip zone

This commit is contained in:
Manu Mtz.-Almeida
2019-07-06 19:33:34 +02:00
parent 7953088418
commit e059fc8048
19 changed files with 137 additions and 131 deletions

View File

@ -10,7 +10,14 @@ export function appInitialize(config: Config, doc: Document, zone: NgZone) {
if (win) {
const Ionic = win.Ionic = win.Ionic || {};
Ionic.config = config;
Ionic.config = {
...config,
_zoneGate: (h: any) => zone.run(h)
};
const aelFn = '__zone_symbol__addEventListener' in (document.body as any)
? '__zone_symbol__addEventListener'
: 'addEventListener';
return applyPolyfills().then(() => {
return defineCustomElements(win, {
@ -23,41 +30,13 @@ export function appInitialize(config: Config, doc: Document, zone: NgZone) {
});
},
ael(elm, eventName, cb, opts) {
if ((elm as any).__zone_symbol__addEventListener && skipZone(eventName)) {
(elm as any).__zone_symbol__addEventListener(eventName, cb, opts);
} else {
elm.addEventListener(eventName, cb, opts);
}
(elm as any)[aelFn](eventName, cb, opts);
},
rel(elm, eventName, cb, opts) {
if ((elm as any).__zone_symbol__removeEventListener && skipZone(eventName)) {
(elm as any).__zone_symbol__removeEventListener(eventName, cb, opts);
} else {
elm.removeEventListener(eventName, cb, opts);
}
elm.removeEventListener(eventName, cb, opts);
}
});
});
}
};
}
const SKIP_ZONE = [
'scroll',
'resize',
'touchstart',
'touchmove',
'touchend',
'mousedown',
'mousemove',
'mouseup',
'ionStyle',
'ionTabButtonClick'
];
function skipZone(eventName: string) {
return SKIP_ZONE.indexOf(eventName) >= 0;
}

View File

@ -42,16 +42,14 @@ export class ValueAccessor implements ControlValueAccessor {
}
export function setIonicClasses(element: ElementRef) {
requestAnimationFrame(() => {
const input = element.nativeElement as HTMLElement;
const classes = getClasses(input);
setClasses(input, classes);
const input = element.nativeElement as HTMLElement;
const classes = getClasses(input);
setClasses(input, classes);
const item = input.closest('ion-item');
if (item) {
setClasses(item, classes);
}
});
const item = input.closest('ion-item');
if (item) {
setClasses(item, classes);
}
}
function getClasses(element: HTMLElement) {

View File

@ -1,5 +1,5 @@
import { Location } from '@angular/common';
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
import { Attribute, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET, Router } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
@ -57,7 +57,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
private resolver: ComponentFactoryResolver,
@Attribute('name') name: string,
@Optional() @Attribute('tabs') tabs: string,
private changeDetector: ChangeDetectorRef,
private config: Config,
private navCtrl: NavController,
commonLocation: Location,
@ -206,12 +205,11 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
// Calling `markForCheck` to make sure we will run the change detection when the
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
enteringView = this.stackCtrl.createView(this.activated, activatedRoute);
enteringView.ref.changeDetectorRef.detectChanges();
// Store references to the proxy by component
this.proxyMap.set(cmpRef.instance, activatedRouteProxy);
this.currentActivatedRoute$.next({ component: cmpRef.instance, activatedRoute });
this.changeDetector.markForCheck();
}
this.activatedView = enteringView;

View File

@ -44,11 +44,7 @@ export class StackController {
getExistingView(activatedRoute: ActivatedRoute): RouteView | undefined {
const activatedUrlKey = getUrl(this.router, activatedRoute);
const view = this.views.find(vw => vw.url === activatedUrlKey);
if (view) {
view.ref.changeDetectorRef.reattach();
}
return view;
return this.views.find(vw => vw.url === activatedUrlKey);
}
setActive(enteringView: RouteView): Promise<StackEvent> {
@ -95,15 +91,15 @@ export class StackController {
}
const views = this.insertView(enteringView, direction);
return this.wait(async () => {
await this.transition(enteringView, leavingView, animation, this.canGoBack(1), false);
await cleanupAsync(enteringView, views, viewsSnapshot, this.location);
return {
enteringView,
direction,
animation,
tabSwitch
};
return this.wait(() => {
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false)
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
.then(() => ({
enteringView,
direction,
animation,
tabSwitch
}));
});
}
@ -138,13 +134,12 @@ export class StackController {
});
}
async startBackTransition() {
startBackTransition() {
const leavingView = this.activeView;
if (leavingView) {
const views = this.getStack(leavingView.stackId);
const enteringView = views[views.length - 2];
enteringView.ref.changeDetectorRef.reattach();
await this.wait(() => {
return this.wait(() => {
return this.transition(
enteringView, // entering view
leavingView, // leaving view
@ -154,6 +149,7 @@ export class StackController {
);
});
}
return Promise.resolve();
}
endBackTransition(shouldComplete: boolean) {
@ -189,7 +185,7 @@ export class StackController {
return this.views.slice();
}
private async transition(
private transition(
enteringView: RouteView | undefined,
leavingView: RouteView | undefined,
direction: 'forward' | 'back' | undefined,
@ -198,7 +194,13 @@ export class StackController {
) {
if (this.skipTransition) {
this.skipTransition = false;
return;
return Promise.resolve(false);
}
if (enteringView) {
enteringView.ref.changeDetectorRef.reattach();
}
if (leavingView) {
leavingView.ref.changeDetectorRef.detach();
}
const enteringEl = enteringView ? enteringView.element : undefined;
const leavingEl = leavingView ? leavingView.element : undefined;
@ -209,15 +211,15 @@ export class StackController {
containerEl.appendChild(enteringEl);
}
await containerEl.componentOnReady();
await containerEl.commit(enteringEl, leavingEl, {
return this.zone.runOutsideAngular(() => containerEl.commit(enteringEl, leavingEl, {
deepWait: true,
duration: direction === undefined ? 0 : undefined,
direction,
showGoBack,
progressAnimation
});
}));
}
return Promise.resolve(false);
}
private async wait<T>(task: () => Promise<T>): Promise<T> {
@ -245,7 +247,6 @@ function cleanup(activeRoute: RouteView, views: RouteView[], viewsSnapshot: Rout
.forEach(destroyView);
views.forEach(view => {
/**
* In the event that a user navigated multiple
* times in rapid succession, we want to make sure