Skip to content

Commit

Permalink
feat(core): Add zoneless change detection provider as experimental (#…
Browse files Browse the repository at this point in the history
…55329)

This commit adds the zoneless change detection provider function to the
public API surface as experimental.

PR Close #55329
  • Loading branch information
atscott authored and pkozlowski-opensource committed Apr 16, 2024
1 parent 785c3c1 commit f09c5a7
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 5 deletions.
3 changes: 3 additions & 0 deletions goldens/public-api/core/index.md
Expand Up @@ -1353,6 +1353,9 @@ export class PlatformRef {
// @public
export type Predicate<T> = (value: T) => boolean;

// @public
export function provideExperimentalZonelessChangeDetection(): EnvironmentProviders;

// @public
export type Provider = TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | ExistingProvider | FactoryProvider | any[];

Expand Down
Expand Up @@ -142,7 +142,47 @@ export class ChangeDetectionSchedulerImpl implements ChangeDetectionScheduler {
}
}

export function provideZonelessChangeDetection(): EnvironmentProviders {

/**
* Provides change detection without ZoneJS for the application bootstrapped using
* `bootstrapApplication`.
*
* This function allows you to configure the application to not use the state/state changes of
* ZoneJS to schedule change detection in the application. This will work when ZoneJS is not present
* on the page at all or if it exists because something else is using it (either another Angular
* application which uses ZoneJS for scheduling or some other library that relies on ZoneJS).
*
* This can also be added to the `TestBed` providers to configure the test environment to more
* closely match production behavior. This will help give higher confidence that components are
* compatible with zoneless change detection.
*
* ZoneJS uses browser events to trigger change detection. When using this provider, Angular will
* instead use Angular APIs to schedule change detection. These APIs include:
*
* - `ChangeDetectorRef.markForCheck`
* - `ComponentRef.setInput`
* - updating a signal that is read in a template
* - when bound host or template listeners are triggered
* - attaching a view that was marked dirty by one of the above
* - removing a view
* - registering a render hook (templates are only refreshed if render hooks do one of the above)
*
* @usageNotes
* ```typescript
* bootstrapApplication(MyApp, {providers: [
* provideExperimentalZonelessChangeDetection(),
* ]});
* ```
*
* This API is experimental. Neither the shape, nor the underlying behavior is stable and can change
* in patch versions. There are known feature gaps, including the lack of a public zoneless API
* which prevents the application from serializing too early with SSR.
*
* @publicApi
* @experimental
* @see {@link bootstrapApplication}
*/
export function provideExperimentalZonelessChangeDetection(): EnvironmentProviders {
performanceMarkFeature('NgZoneless');
return makeEnvironmentProviders([
{provide: ChangeDetectionScheduler, useExisting: ChangeDetectionSchedulerImpl},
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/core.ts
Expand Up @@ -28,6 +28,7 @@ export {BootstrapOptions, ApplicationRef, NgProbeToken, APP_BOOTSTRAP_LISTENER}
export {PlatformRef} from './platform/platform_ref';
export {createPlatform, createPlatformFactory, assertPlatform, destroyPlatform, getPlatform} from './platform/platform';
export {provideZoneChangeDetection, NgZoneOptions} from './change_detection/scheduling/ng_zone_scheduling';
export {provideExperimentalZonelessChangeDetection} from './change_detection/scheduling/zoneless_scheduling_impl';
export {enableProdMode, isDevMode} from './util/is_dev_mode';
export {APP_ID, PACKAGE_ROOT_URL, PLATFORM_INITIALIZER, PLATFORM_ID, ANIMATION_MODULE_TYPE, CSP_NONCE} from './application/application_tokens';
export {APP_INITIALIZER, ApplicationInitStatus} from './application/application_init';
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/core_private_export.ts
Expand Up @@ -12,7 +12,6 @@ export {IMAGE_CONFIG as ɵIMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS as ɵIMAGE_CONFIG_
export {internalCreateApplication as ɵinternalCreateApplication} from './application/create_application';
export {defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers} from './change_detection/change_detection';
export {ChangeDetectionScheduler as ɵChangeDetectionScheduler, ZONELESS_ENABLED as ɵZONELESS_ENABLED} from './change_detection/scheduling/zoneless_scheduling';
export {provideZonelessChangeDetection as ɵprovideZonelessChangeDetection} from './change_detection/scheduling/zoneless_scheduling_impl';
export {Console as ɵConsole} from './console';
export {DeferBlockDetails as ɵDeferBlockDetails, getDeferBlocks as ɵgetDeferBlocks} from './defer/discovery';
export {renderDeferBlockState as ɵrenderDeferBlockState, triggerResourceLoading as ɵtriggerResourceLoading} from './defer/instructions';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/change_detection_scheduler_spec.ts
Expand Up @@ -8,7 +8,7 @@

import {AsyncPipe} from '@angular/common';
import {PLATFORM_BROWSER_ID} from '@angular/common/src/platform_id';
import {afterNextRender, afterRender, ApplicationRef, ChangeDetectorRef, Component, createComponent, destroyPlatform, ElementRef, EnvironmentInjector, ErrorHandler, inject, Input, NgZone, PLATFORM_ID, provideZoneChangeDetection, signal, TemplateRef, Type, ViewChild, ViewContainerRef, ɵprovideZonelessChangeDetection as provideZonelessChangeDetection} from '@angular/core';
import {afterNextRender, afterRender, ApplicationRef, ChangeDetectorRef, Component, createComponent, destroyPlatform, ElementRef, EnvironmentInjector, ErrorHandler, inject, Input, NgZone, PLATFORM_ID, provideExperimentalZonelessChangeDetection as provideZonelessChangeDetection, provideZoneChangeDetection, signal, TemplateRef, Type, ViewChild, ViewContainerRef} from '@angular/core';
import {toSignal} from '@angular/core/rxjs-interop';
import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from '@angular/core/testing';
import {bootstrapApplication} from '@angular/platform-browser';
Expand Down
4 changes: 2 additions & 2 deletions packages/core/test/component_fixture_spec.ts
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Component, Injectable, Input, signal, ɵprovideZonelessChangeDetection} from '@angular/core';
import {Component, Injectable, Input, provideExperimentalZonelessChangeDetection, signal} from '@angular/core';
import {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestBed, waitForAsync, withModule} from '@angular/core/testing';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers';
Expand Down Expand Up @@ -373,7 +373,7 @@ describe('ComponentFixture with zoneless', () => {
it('will not refresh CheckAlways views when detectChanges is called if not marked dirty', () => {
TestBed.configureTestingModule({
providers: [
ɵprovideZonelessChangeDetection(),
provideExperimentalZonelessChangeDetection(),
{provide: AllowDetectChangesAndAcknowledgeItCanHideApplicationBugs, useValue: true},
]
});
Expand Down

0 comments on commit f09c5a7

Please sign in to comment.