From e25c5b3fb11144d9ba6efcde155fee276c64f1c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Fri, 12 Apr 2024 14:41:51 +0200 Subject: [PATCH] feat(angular): use zone eventCoalescing by default --- .../__snapshots__/application.spec.ts.snap | 19 ++++++++--- .../application/application.spec.ts | 34 +++++++++++++++++++ .../files/ng-module/src/main.ts__tpl__ | 4 ++- .../src/app/app.config.ts__tpl__ | 4 +-- .../application/lib/create-files.ts | 1 + .../host/__snapshots__/host.spec.ts.snap | 24 +++++++++---- .../ngrx-root-store.spec.ts.snap | 16 ++++----- .../ngrx/__snapshots__/ngrx.spec.ts.snap | 12 +++---- .../remote/__snapshots__/remote.spec.ts.snap | 8 +++-- .../generators/setup-ssr/setup-ssr.spec.ts | 16 +++++---- 10 files changed, 103 insertions(+), 35 deletions(-) diff --git a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap index 11b543fc29b5b..8791a99d52b97 100644 --- a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap @@ -620,12 +620,12 @@ bootstrapApplication(AppComponent, appConfig).catch((err) => `; exports[`app --standalone should generate a standalone app correctly with routing 2`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; export const appConfig: ApplicationConfig = { - providers: [provideRouter(appRoutes) ] + providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; @@ -698,10 +698,10 @@ bootstrapApplication(AppComponent, appConfig).catch((err) => `; exports[`app --standalone should generate a standalone app correctly without routing 2`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; export const appConfig: ApplicationConfig = { - providers: [] + providers: [provideZoneChangeDetection({ eventCoalescing: true }), ] }; " `; @@ -753,6 +753,17 @@ describe('AppComponent', () => { " `; +exports[`app --standalone should should not use event coalescing in versions lower than v18 1`] = ` +"import { ApplicationConfig } from '@angular/core'; +import { provideRouter } from '@angular/router'; +import { appRoutes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [provideRouter(appRoutes) ] +}; +" +`; + exports[`app --strict should enable strict type checking: app tsconfig.json 1`] = ` { "angularCompilerOptions": { diff --git a/packages/angular/src/generators/application/application.spec.ts b/packages/angular/src/generators/application/application.spec.ts index f9a00cb4a3ace..fbb722c607eb9 100644 --- a/packages/angular/src/generators/application/application.spec.ts +++ b/packages/angular/src/generators/application/application.spec.ts @@ -892,6 +892,19 @@ describe('app', () => { appTree.read('standalone/src/app/nx-welcome.component.ts', 'utf-8') ).toContain('standalone: true'); }); + + it('should should not use event coalescing in versions lower than v18', async () => { + updateJson(appTree, 'package.json', (json) => ({ + ...json, + dependencies: { ...json.dependencies, '@angular/core': '~17.0.0' }, + })); + + await generateApp(appTree, 'standalone', { standalone: true }); + + expect( + appTree.read('standalone/src/app/app.config.ts', 'utf-8') + ).toMatchSnapshot(); + }); }); it('should generate correct main.ts', async () => { @@ -899,6 +912,27 @@ describe('app', () => { await generateApp(appTree, 'myapp'); // ASSERT + expect(appTree.read('myapp/src/main.ts', 'utf-8')).toMatchInlineSnapshot(` + "import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + import { AppModule } from './app/app.module'; + + platformBrowserDynamic() + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true + }) + .catch((err) => console.error(err)); + " + `); + }); + + it('should should not use event coalescing in versions lower than v18', async () => { + updateJson(appTree, 'package.json', (json) => ({ + ...json, + dependencies: { ...json.dependencies, '@angular/core': '~17.0.0' }, + })); + + await generateApp(appTree, 'myapp'); + expect(appTree.read('myapp/src/main.ts', 'utf-8')).toMatchInlineSnapshot(` "import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; diff --git a/packages/angular/src/generators/application/files/ng-module/src/main.ts__tpl__ b/packages/angular/src/generators/application/files/ng-module/src/main.ts__tpl__ index 16de2365d275e..b84d7f7305cc1 100644 --- a/packages/angular/src/generators/application/files/ng-module/src/main.ts__tpl__ +++ b/packages/angular/src/generators/application/files/ng-module/src/main.ts__tpl__ @@ -2,5 +2,7 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule<% if (useEventCoalescing) { %>, { + ngZoneEventCoalescing: true + }<% } %>) .catch((err) => console.error(err)); diff --git a/packages/angular/src/generators/application/files/standalone-components/src/app/app.config.ts__tpl__ b/packages/angular/src/generators/application/files/standalone-components/src/app/app.config.ts__tpl__ index aba1bdf1c7def..3052cc33c89b7 100644 --- a/packages/angular/src/generators/application/files/standalone-components/src/app/app.config.ts__tpl__ +++ b/packages/angular/src/generators/application/files/standalone-components/src/app/app.config.ts__tpl__ @@ -1,7 +1,7 @@ -import { ApplicationConfig } from <% if (angularMajorVersion >= 16) { %>'@angular/core';<% } else { %>'@angular/platform-browser';<% } %><% if (routing) { %> +import { ApplicationConfig<% if (useEventCoalescing) { %>, provideZoneChangeDetection<% } %> } from <% if (angularMajorVersion >= 16) { %>'@angular/core';<% } else { %>'@angular/platform-browser';<% } %><% if (routing) { %> import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes';<% } %> export const appConfig: ApplicationConfig = { - providers: [<% if (routing) { %>provideRouter(appRoutes) <% } %>] + providers: [<% if (useEventCoalescing) { %>provideZoneChangeDetection({ eventCoalescing: true }), <% } %><% if (routing) { %>provideRouter(appRoutes) <% } %>] }; diff --git a/packages/angular/src/generators/application/lib/create-files.ts b/packages/angular/src/generators/application/lib/create-files.ts index a9396186e0b9d..e01a94022856c 100644 --- a/packages/angular/src/generators/application/lib/create-files.ts +++ b/packages/angular/src/generators/application/lib/create-files.ts @@ -36,6 +36,7 @@ export async function createFiles( angularMajorVersion, rootOffset, isUsingApplicationBuilder, + useEventCoalescing: angularMajorVersion >= 18, tpl: '', }; diff --git a/packages/angular/src/generators/host/__snapshots__/host.spec.ts.snap b/packages/angular/src/generators/host/__snapshots__/host.spec.ts.snap index 2e50e3c16472e..9e151a6b1ce13 100644 --- a/packages/angular/src/generators/host/__snapshots__/host.spec.ts.snap +++ b/packages/angular/src/generators/host/__snapshots__/host.spec.ts.snap @@ -96,7 +96,9 @@ exports[`Host App Generator --ssr should generate the correct files 2`] = ` import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true, + }) .catch((err) => console.error(err)); " `; @@ -408,13 +410,17 @@ export const appRoutes: Route[] = [ `; exports[`Host App Generator --ssr should generate the correct files for standalone 8`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideClientHydration } from '@angular/platform-browser'; export const appConfig: ApplicationConfig = { - providers: [provideClientHydration(), provideRouter(appRoutes)], + providers: [ + provideClientHydration(), + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(appRoutes), + ], }; " `; @@ -619,13 +625,17 @@ export const appRoutes: Route[] = [ `; exports[`Host App Generator --ssr should generate the correct files for standalone when --typescript=true 8`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideClientHydration } from '@angular/platform-browser'; export const appConfig: ApplicationConfig = { - providers: [provideClientHydration(), provideRouter(appRoutes)], + providers: [ + provideClientHydration(), + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(appRoutes), + ], }; " `; @@ -716,7 +726,9 @@ exports[`Host App Generator --ssr should generate the correct files when --types import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true, + }) .catch((err) => console.error(err)); " `; diff --git a/packages/angular/src/generators/ngrx-root-store/__snapshots__/ngrx-root-store.spec.ts.snap b/packages/angular/src/generators/ngrx-root-store/__snapshots__/ngrx-root-store.spec.ts.snap index ab502ac9c9ed5..f6154e3a36471 100644 --- a/packages/angular/src/generators/ngrx-root-store/__snapshots__/ngrx-root-store.spec.ts.snap +++ b/packages/angular/src/generators/ngrx-root-store/__snapshots__/ngrx-root-store.spec.ts.snap @@ -426,7 +426,7 @@ export class AppModule {} `; exports[`NgRxRootStoreGenerator Standalone APIs should add a facade when --facade=true 1`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore, provideState } from '@ngrx/store'; @@ -436,7 +436,7 @@ import { UsersEffects } from './+state/users.effects'; import { UsersFacade } from './+state/users.facade'; export const appConfig: ApplicationConfig = { - providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),UsersFacade,provideEffects(),provideStore(),provideRouter(appRoutes) ] + providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),UsersFacade,provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; @@ -473,7 +473,7 @@ export class UsersFacade { `; exports[`NgRxRootStoreGenerator Standalone APIs should add a root module and root state when --minimal=false 1`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore, provideState } from '@ngrx/store'; @@ -482,7 +482,7 @@ import * as fromUsers from './+state/users.reducer'; import { UsersEffects } from './+state/users.effects'; export const appConfig: ApplicationConfig = { - providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideRouter(appRoutes) ] + providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; @@ -722,20 +722,20 @@ describe('Users Selectors', () => { `; exports[`NgRxRootStoreGenerator Standalone APIs should add an empty root module when --minimal=true 1`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore } from '@ngrx/store'; import { provideEffects } from '@ngrx/effects'; export const appConfig: ApplicationConfig = { - providers: [provideEffects(),provideStore(),provideRouter(appRoutes) ] + providers: [provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; exports[`NgRxRootStoreGenerator Standalone APIs should instrument the store devtools when "addDevTools: true" 1`] = ` -"import { ApplicationConfig, isDevMode } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection, isDevMode } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore } from '@ngrx/store'; @@ -743,7 +743,7 @@ import { provideEffects } from '@ngrx/effects'; import { provideStoreDevtools } from '@ngrx/store-devtools'; export const appConfig: ApplicationConfig = { - providers: [provideStoreDevtools({ logOnly: !isDevMode() }),provideEffects(),provideStore(),provideRouter(appRoutes) ] + providers: [provideStoreDevtools({ logOnly: !isDevMode() }),provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; diff --git a/packages/angular/src/generators/ngrx/__snapshots__/ngrx.spec.ts.snap b/packages/angular/src/generators/ngrx/__snapshots__/ngrx.spec.ts.snap index d29c025109be9..98d812a7df048 100644 --- a/packages/angular/src/generators/ngrx/__snapshots__/ngrx.spec.ts.snap +++ b/packages/angular/src/generators/ngrx/__snapshots__/ngrx.spec.ts.snap @@ -756,7 +756,7 @@ bootstrapApplication(AppComponent, appConfig).catch((err) => `; exports[`ngrx Standalone APIs should add a root module with feature module when minimal is set to false 2`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore, provideState } from '@ngrx/store'; @@ -765,7 +765,7 @@ import * as fromUsers from './+state/users.reducer'; import { UsersEffects } from './+state/users.effects'; export const appConfig: ApplicationConfig = { - providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideRouter(appRoutes) ] + providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; @@ -782,14 +782,14 @@ bootstrapApplication(AppComponent, appConfig).catch((err) => `; exports[`ngrx Standalone APIs should add an empty provideStore when minimal and root are set to true 2`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore, provideState } from '@ngrx/store'; import { provideEffects } from '@ngrx/effects'; export const appConfig: ApplicationConfig = { - providers: [provideEffects(),provideStore(),provideRouter(appRoutes) ] + providers: [provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; @@ -806,7 +806,7 @@ bootstrapApplication(AppComponent, appConfig).catch((err) => `; exports[`ngrx Standalone APIs should add facade provider when facade is true 2`] = ` -"import { ApplicationConfig } from '@angular/core'; +"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideStore, provideState } from '@ngrx/store'; @@ -816,7 +816,7 @@ import { UsersEffects } from './+state/users.effects'; import { UsersFacade } from './+state/users.facade'; export const appConfig: ApplicationConfig = { - providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),UsersFacade,provideRouter(appRoutes) ] + providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),UsersFacade,provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `; diff --git a/packages/angular/src/generators/remote/__snapshots__/remote.spec.ts.snap b/packages/angular/src/generators/remote/__snapshots__/remote.spec.ts.snap index a06a027cc6f83..7bd6129de18e3 100644 --- a/packages/angular/src/generators/remote/__snapshots__/remote.spec.ts.snap +++ b/packages/angular/src/generators/remote/__snapshots__/remote.spec.ts.snap @@ -111,7 +111,9 @@ exports[`MF Remote App Generator --ssr should generate the correct files 2`] = ` import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true, + }) .catch((err) => console.error(err)); " `; @@ -333,7 +335,9 @@ exports[`MF Remote App Generator --ssr should generate the correct files when -- import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true, + }) .catch((err) => console.error(err)); " `; diff --git a/packages/angular/src/generators/setup-ssr/setup-ssr.spec.ts b/packages/angular/src/generators/setup-ssr/setup-ssr.spec.ts index a49a6433afb66..644bcfa577a43 100644 --- a/packages/angular/src/generators/setup-ssr/setup-ssr.spec.ts +++ b/packages/angular/src/generators/setup-ssr/setup-ssr.spec.ts @@ -46,7 +46,9 @@ describe('setupSSR', () => { import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true, + }) .catch((err) => console.error(err)); " `); @@ -212,7 +214,9 @@ describe('setupSSR', () => { import { AppModule } from './app/app.module'; platformBrowserDynamic() - .bootstrapModule(AppModule) + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true + }) .catch((err) => console.error(err)); " `); @@ -462,13 +466,13 @@ describe('setupSSR', () => { // ASSERT expect(tree.read('app1/src/app/app.config.ts', 'utf-8')) .toMatchInlineSnapshot(` - "import { ApplicationConfig } from '@angular/core'; + "import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; import { provideClientHydration } from '@angular/platform-browser'; export const appConfig: ApplicationConfig = { - providers: [provideClientHydration(),provideRouter(appRoutes) ] + providers: [provideClientHydration(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ] }; " `); @@ -540,12 +544,12 @@ describe('setupSSR', () => { expect(tree.read('app1/src/app/app.config.ts', 'utf-8')) .toMatchInlineSnapshot(` - "import { ApplicationConfig } from '@angular/core'; + "import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter, withEnabledBlockingInitialNavigation } from '@angular/router'; import { appRoutes } from './app.routes'; export const appConfig: ApplicationConfig = { - providers: [provideRouter(appRoutes, withEnabledBlockingInitialNavigation()) ] + providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes, withEnabledBlockingInitialNavigation()) ] }; " `);