6

I created an Angular issue: https://github.com/angular/angular/issues/20471

Also started a proposal in gist: https://gist.github.com/matthewharwood/23ea18c8509b8056813d3c3e7df0d1b2

Hey I was messing with the Angular/cdk directive which works outside of ngZones and @angular/animations. I was wonder if you could tell me if a particular layout thrashing optimization is taken into account? My secret weapon for performance has always been to use fastdom library for effects like parallax scrolling. I've yet to test perf because I have a feeling that angular already has methods similar too fastdom, that I just don't know about.

Question: Does Angular have any method for scheduling measures and mutates of the DOM? If so, how? If not, would it be wise to implement fastdom into libraries like cdk and animations, if so again, could you give me some examples to help me communicate this better to the angular team?

Anyways describing the problem is a bit hard to explain; however, lets look at the fastdom and I'll move to angular afterwards.

Fastdom works like this:

fastdom.measure(() => {
  console.log('measure');
});

fastdom.mutate(() => {
  console.log('mutate');
});

fastdom.measure(() => {
  console.log('measure');
});

fastdom.mutate(() => {
  console.log('mutate');
});

Would output:

measure
measure
mutate
mutate

When looking at cdk: https://sourcegraph.com/github.com/angular/material2@master/-/blob/src/cdk/scrolling/scrollable.ts

doesn't seem to have kind of measure wrapper unless ngZones is it.

  ngOnInit() {
    this._scrollListener = this._ngZone.runOutsideAngular(() => {
      return this._renderer.listen(this.getElementRef().nativeElement, 'scroll', (event: Event) => {
        this._elementScrolled.next(event);
      });
    });

    this._scroll.register(this);
  }

Test case: Imagine you had a element on a page that would translate based on the current scroll position.

You could implement this in something like: (Pseudo code)

// index.html
<body [cdkScrollable]>
    <some-component></some-component>
</body>


// some-component.ts
@Component({
  selector: 'some-component'
})
export class SomeComponent implement OnInit, AfterViewInit {
   @ViewChild(CdkScrollable) child: cdkScrollable;
    private _el: any;
     constructor(private _elementRef: ElementRef, private _renderer: Renderer2){}

    ngOnInit() {
      this._el = this._renderer.selectRootElement(this._elementRef);
     }

     ngAfterViewInit() {
        this._makeAnimation()
     }

   private _makeAnimation() {
    // first build the animation
    const myAnimation = this._builder.build([
      style({ top: 0 }),
      animate(1000, style({ top: `${cdkScrollable. elementScrolled(). scrollTop + 100}px` }))
    ]);

    // then create a player from it
    const player = myAnimation.create(this._el.nativeElement);

    player.play();
  }
}

Over something like this if you used fast dom:

// this should need optimization to run outside of angular too.
@Component({
  selector: 'some-other-component'
}) 
export class SomeOtherComponent {
  private _el: any;
  constructor(private _elementRef: ElementRef, private _renderer: Renderer2){}

  public ngOnInit() {
     this._el = this._renderer.selectRootElement(this._elementRef);
     this.renderLoop_();
  }

 private renderLoop_() {
    this.renderScrollBar_();
    fd.measure(() => this.renderLoop_());
  }

  private renderScrollBar() {
    fd.measure(() => {
      const scroll = window.scrollY + 100; 
      fd.mutate(() => {
         this._el.top = `${scroll}px`;
      });
    });
  }
}

I'm pretty certain that this kind of optimization isn't included unless this._ngZone.runOutsideAngular is that optimization. Does anyone have any insight into the presence of optimization?

Armeen Moon
  • 18,061
  • 35
  • 120
  • 233

0 Answers0