Skip to content

Commit f233dae

Browse files
feat(component): use global render strategy in zone-less mode (#3379)
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.
1 parent 7957bf3 commit f233dae

File tree

6 files changed

+34
-18
lines changed

6 files changed

+34
-18
lines changed

modules/component/spec/core/render-scheduler.spec.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { NgZone } from '@angular/core';
1+
import * as angular from '@angular/core';
2+
import { noop } from 'rxjs';
23
import { createRenderScheduler } from '../../src/core/render-scheduler';
34
import {
45
manualInstanceNgZone,
@@ -7,27 +8,32 @@ import {
78
} from '../fixtures/fixtures';
89

910
describe('createRenderScheduler', () => {
10-
function setup(ngZone: NgZone) {
11+
function setup(ngZone: angular.NgZone) {
1112
const cdRef = new MockChangeDetectorRef();
1213
const renderScheduler = createRenderScheduler({ ngZone, cdRef });
14+
jest.spyOn(angular, 'ɵmarkDirty').mockImplementation(noop);
1315

14-
return { cdRef, renderScheduler };
16+
return { cdRef, renderScheduler, markDirty: angular.ɵmarkDirty };
1517
}
1618

1719
describe('schedule', () => {
1820
it('should call markForCheck in zone-full mode', () => {
19-
const { cdRef, renderScheduler } = setup(manualInstanceNgZone);
21+
const { cdRef, renderScheduler, markDirty } = setup(manualInstanceNgZone);
2022
renderScheduler.schedule();
2123

22-
expect(cdRef.detectChanges).toHaveBeenCalledTimes(0);
24+
expect(markDirty).toHaveBeenCalledTimes(0);
2325
expect(cdRef.markForCheck).toHaveBeenCalledTimes(1);
2426
});
2527

26-
it('should call detectChanges in zone-less mode', () => {
27-
const { cdRef, renderScheduler } = setup(manualInstanceNoopNgZone);
28+
it('should call markDirty in zone-less mode', () => {
29+
const { cdRef, renderScheduler, markDirty } = setup(
30+
manualInstanceNoopNgZone
31+
);
2832
renderScheduler.schedule();
2933

30-
expect(cdRef.detectChanges).toHaveBeenCalledTimes(1);
34+
expect(markDirty).toHaveBeenCalledWith(
35+
(cdRef as unknown as { context: object }).context
36+
);
3137
expect(cdRef.markForCheck).toHaveBeenCalledTimes(0);
3238
});
3339
});

modules/component/spec/fixtures/fixtures.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export class MockChangeDetectorRef {
2121
checkNoChanges = jest.fn();
2222
detach = jest.fn();
2323
reattach = jest.fn();
24+
context = { x: 1, y: 2 };
2425
}
2526

2627
export class MockErrorHandler {

modules/component/src/core/render-scheduler.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { ChangeDetectorRef, NgZone } from '@angular/core';
1+
import {
2+
ChangeDetectorRef,
3+
NgZone,
4+
ɵmarkDirty as markDirty,
5+
} from '@angular/core';
26

37
export interface RenderScheduler {
48
schedule(): void;
@@ -16,7 +20,8 @@ export function createRenderScheduler(
1620
if (hasZone(config.ngZone)) {
1721
config.cdRef.markForCheck();
1822
} else {
19-
config.cdRef.detectChanges();
23+
const context = getCdRefContext(config.cdRef);
24+
markDirty(context);
2025
}
2126
}
2227

@@ -30,3 +35,7 @@ export function createRenderScheduler(
3035
function hasZone(z: NgZone): boolean {
3136
return z instanceof NgZone;
3237
}
38+
39+
function getCdRefContext(cdRef: ChangeDetectorRef): object {
40+
return (cdRef as unknown as { context: object }).context;
41+
}

modules/component/src/push/push.pipe.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ import { createRenderEventManager } from '../core/render-event/manager';
3939
* Included Features:
4040
* - Take observables or promises, retrieve their values and render the value to the template
4141
* - Handling null and undefined values in a clean unified/structured way
42-
* - Triggers change-detection differently if `zone.js` is present or not (`detectChanges` or `markForCheck`)
43-
* - Distinct same values in a row to increase performance
44-
* - Coalescing of change detection calls to boost performance
42+
* - Triggers the change detection differently if `zone.js` is present or not
43+
* using `ChangeDetectorRef.markForCheck` or `ɵmarkDirty`
44+
* - Distinct the same values in a row for better performance
4545
*
4646
* @usageNotes
4747
*

projects/ngrx.io/content/guide/component/let.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,5 @@ the suspense template will be displayed again until the new observable emits the
9595
- Takes away the multiple usages of the `async` or `ngrxPush` pipe.
9696
- Provides a unified/structured way of handling `null` and `undefined`.
9797
- Triggers the change detection differently if `zone.js` is present or not
98-
using the `ChangeDetectorRef.markForCheck` or `ChangeDetectorRef.detectChanges`.
99-
- Distinct the same values in a row using the `distinctUntilChanged` operator.
98+
using `ChangeDetectorRef.markForCheck` or `ɵmarkDirty`.
99+
- Distinct the same values in a row for better performance.

projects/ngrx.io/content/guide/component/push.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ lean to bad performance or even unusable applications, but the `async` pipe does
5555

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

0 commit comments

Comments
 (0)