Skip to content

Commit

Permalink
feat(component): use global render strategy in zone-less mode (#3379)
Browse files Browse the repository at this point in the history
Closes #3342

BREAKING CHANGES:

The native local rendering strategy is replaced by global
in zone-less mode for better performance.

BEFORE:

The change detection is triggered via `changeDetectorRef.detectChanges`
in zone-less mode.

AFTER:

The change detection is triggered via `ɵmarkDirty` in zone-less mode.
  • Loading branch information
markostanimirovic committed May 23, 2022
1 parent 7957bf3 commit f233dae
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 18 deletions.
22 changes: 14 additions & 8 deletions modules/component/spec/core/render-scheduler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NgZone } from '@angular/core';
import * as angular from '@angular/core';
import { noop } from 'rxjs';
import { createRenderScheduler } from '../../src/core/render-scheduler';
import {
manualInstanceNgZone,
Expand All @@ -7,27 +8,32 @@ import {
} from '../fixtures/fixtures';

describe('createRenderScheduler', () => {
function setup(ngZone: NgZone) {
function setup(ngZone: angular.NgZone) {
const cdRef = new MockChangeDetectorRef();
const renderScheduler = createRenderScheduler({ ngZone, cdRef });
jest.spyOn(angular, 'ɵmarkDirty').mockImplementation(noop);

return { cdRef, renderScheduler };
return { cdRef, renderScheduler, markDirty: angular.ɵmarkDirty };
}

describe('schedule', () => {
it('should call markForCheck in zone-full mode', () => {
const { cdRef, renderScheduler } = setup(manualInstanceNgZone);
const { cdRef, renderScheduler, markDirty } = setup(manualInstanceNgZone);
renderScheduler.schedule();

expect(cdRef.detectChanges).toHaveBeenCalledTimes(0);
expect(markDirty).toHaveBeenCalledTimes(0);
expect(cdRef.markForCheck).toHaveBeenCalledTimes(1);
});

it('should call detectChanges in zone-less mode', () => {
const { cdRef, renderScheduler } = setup(manualInstanceNoopNgZone);
it('should call markDirty in zone-less mode', () => {
const { cdRef, renderScheduler, markDirty } = setup(
manualInstanceNoopNgZone
);
renderScheduler.schedule();

expect(cdRef.detectChanges).toHaveBeenCalledTimes(1);
expect(markDirty).toHaveBeenCalledWith(
(cdRef as unknown as { context: object }).context
);
expect(cdRef.markForCheck).toHaveBeenCalledTimes(0);
});
});
Expand Down
1 change: 1 addition & 0 deletions modules/component/spec/fixtures/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class MockChangeDetectorRef {
checkNoChanges = jest.fn();
detach = jest.fn();
reattach = jest.fn();
context = { x: 1, y: 2 };
}

export class MockErrorHandler {
Expand Down
13 changes: 11 additions & 2 deletions modules/component/src/core/render-scheduler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ChangeDetectorRef, NgZone } from '@angular/core';
import {
ChangeDetectorRef,
NgZone,
ɵmarkDirty as markDirty,
} from '@angular/core';

export interface RenderScheduler {
schedule(): void;
Expand All @@ -16,7 +20,8 @@ export function createRenderScheduler(
if (hasZone(config.ngZone)) {
config.cdRef.markForCheck();
} else {
config.cdRef.detectChanges();
const context = getCdRefContext(config.cdRef);
markDirty(context);
}
}

Expand All @@ -30,3 +35,7 @@ export function createRenderScheduler(
function hasZone(z: NgZone): boolean {
return z instanceof NgZone;
}

function getCdRefContext(cdRef: ChangeDetectorRef): object {
return (cdRef as unknown as { context: object }).context;
}
6 changes: 3 additions & 3 deletions modules/component/src/push/push.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ import { createRenderEventManager } from '../core/render-event/manager';
* Included Features:
* - Take observables or promises, retrieve their values and render the value to the template
* - Handling null and undefined values in a clean unified/structured way
* - Triggers change-detection differently if `zone.js` is present or not (`detectChanges` or `markForCheck`)
* - Distinct same values in a row to increase performance
* - Coalescing of change detection calls to boost performance
* - Triggers the change detection differently if `zone.js` is present or not
* using `ChangeDetectorRef.markForCheck` or `ɵmarkDirty`
* - Distinct the same values in a row for better performance
*
* @usageNotes
*
Expand Down
4 changes: 2 additions & 2 deletions projects/ngrx.io/content/guide/component/let.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,5 @@ the suspense template will be displayed again until the new observable emits the
- Takes away the multiple usages of the `async` or `ngrxPush` pipe.
- Provides a unified/structured way of handling `null` and `undefined`.
- Triggers the change detection differently if `zone.js` is present or not
using the `ChangeDetectorRef.markForCheck` or `ChangeDetectorRef.detectChanges`.
- Distinct the same values in a row using the `distinctUntilChanged` operator.
using `ChangeDetectorRef.markForCheck` or `ɵmarkDirty`.
- Distinct the same values in a row for better performance.
6 changes: 3 additions & 3 deletions projects/ngrx.io/content/guide/component/push.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ lean to bad performance or even unusable applications, but the `async` pipe does

- Take observables or promises, retrieves their values, and passes the value to the template.
- Handles `null` and `undefined` values in a clean unified/structured way.
- Triggers change-detection differently if `zone.js` is present or not (`detectChanges` or `markForCheck`).
- Distinct same values in a row to increase performance.
- Coalescing of change detection calls to boost performance.
- Triggers the change detection differently if `zone.js` is present or not
using `ChangeDetectorRef.markForCheck` or `ɵmarkDirty`.
- Distinct the same values in a row for better performance.

0 comments on commit f233dae

Please sign in to comment.