Skip to content

Commit 1ada524

Browse files
committed
feat(@schematics/angular): Applications are zoneless by default
This change updates applications to omit the ZoneJS dependency by default. It depends on angular/angular#63382, which allows us to also exclude the `provideZonelessChangeDetection` provider. This change also includes the addition of `provideZoneChangeDetection` in the `initTestEnvironment` when ZoneJS is detected in the configuration (either on window or in the polyfills).
1 parent aeda497 commit 1ada524

File tree

25 files changed

+310
-185
lines changed

25 files changed

+310
-185
lines changed

package.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,20 @@
4646
},
4747
"homepage": "https://github.com/angular/angular-cli",
4848
"devDependencies": {
49-
"@angular/animations": "21.0.0-next.3",
50-
"@angular/cdk": "21.0.0-next.3",
51-
"@angular/common": "21.0.0-next.3",
52-
"@angular/compiler": "21.0.0-next.3",
53-
"@angular/compiler-cli": "21.0.0-next.3",
54-
"@angular/core": "21.0.0-next.3",
55-
"@angular/forms": "21.0.0-next.3",
56-
"@angular/localize": "21.0.0-next.3",
57-
"@angular/material": "21.0.0-next.3",
49+
"@angular/animations": "21.0.0-next.4",
50+
"@angular/cdk": "21.0.0-next.4",
51+
"@angular/common": "21.0.0-next.4",
52+
"@angular/compiler": "21.0.0-next.4",
53+
"@angular/compiler-cli": "21.0.0-next.4",
54+
"@angular/core": "21.0.0-next.4",
55+
"@angular/forms": "21.0.0-next.4",
56+
"@angular/localize": "21.0.0-next.4",
57+
"@angular/material": "21.0.0-next.4",
5858
"@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#5c80533a1292f228111945c42a81614a03be6ab3",
59-
"@angular/platform-browser": "21.0.0-next.3",
60-
"@angular/platform-server": "21.0.0-next.3",
61-
"@angular/router": "21.0.0-next.3",
62-
"@angular/service-worker": "21.0.0-next.3",
59+
"@angular/platform-browser": "21.0.0-next.4",
60+
"@angular/platform-server": "21.0.0-next.4",
61+
"@angular/router": "21.0.0-next.4",
62+
"@angular/service-worker": "21.0.0-next.4",
6363
"@bazel/bazelisk": "1.26.0",
6464
"@bazel/buildifier": "8.2.1",
6565
"@eslint/compat": "1.3.2",

packages/angular/build/src/builders/karma/application_builder.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,18 @@ async function runEsbuild(
190190
context: BuilderContext,
191191
projectSourceRoot: string,
192192
): Promise<[Result & { kind: ResultKind.Full }, AsyncIterator<Result> | null]> {
193+
const usesZoneJS = buildOptions.polyfills?.includes('zone.js');
193194
const virtualTestBedInit = createVirtualModulePlugin({
194195
namespace: 'angular:test-bed-init',
195196
loadContent: async () => {
196197
const contents: string[] = [
197198
// Initialize the Angular testing environment
199+
`import { NgModule${usesZoneJS ? ', provideZoneChangeDetection' : ''} } from '@angular/core';`,
198200
`import { getTestBed } from '@angular/core/testing';`,
199201
`import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';`,
200-
`getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {`,
202+
`@NgModule({ providers: [${usesZoneJS ? 'provideZoneChangeDetection(), ' : ''}], })`,
203+
`export class TestModule {}`,
204+
`getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {`,
201205
` errorOnUnknownElements: true,`,
202206
` errorOnUnknownProperties: true,`,
203207
`});`,

packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import { RunnerOptions } from '../api';
1717
function createTestBedInitVirtualFile(
1818
providersFile: string | undefined,
1919
projectSourceRoot: string,
20+
polyfills: string[] = [],
2021
): string {
22+
const usesZoneJS = polyfills.includes('zone.js');
2123
let providersImport = 'const providers = [];';
2224
if (providersFile) {
2325
const relativePath = path.relative(projectSourceRoot, providersFile);
@@ -28,15 +30,15 @@ function createTestBedInitVirtualFile(
2830

2931
return `
3032
// Initialize the Angular testing environment
31-
import { NgModule } from '@angular/core';
33+
import { NgModule${usesZoneJS ? ', provideZoneChangeDetection' : ''} } from '@angular/core';
3234
import { getTestBed, ɵgetCleanupHook as getCleanupHook } from '@angular/core/testing';
3335
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
3436
${providersImport}
3537
// Same as https://github.com/angular/angular/blob/05a03d3f975771bb59c7eefd37c01fa127ee2229/packages/core/testing/srcs/test_hooks.ts#L21-L29
3638
beforeEach(getCleanupHook(false));
3739
afterEach(getCleanupHook(true));
3840
@NgModule({
39-
providers,
41+
providers: [${usesZoneJS ? 'provideZoneChangeDetection(), ' : ''}...providers],
4042
})
4143
export class TestModule {}
4244
getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
@@ -113,7 +115,11 @@ export async function getVitestBuildOptions(
113115

114116
buildOptions.polyfills = injectTestingPolyfills(buildOptions.polyfills);
115117

116-
const testBedInitContents = createTestBedInitVirtualFile(providersFile, projectSourceRoot);
118+
const testBedInitContents = createTestBedInitVirtualFile(
119+
providersFile,
120+
projectSourceRoot,
121+
buildOptions.polyfills,
122+
);
117123

118124
return {
119125
buildOptions,

packages/angular_devkit/build_angular/src/builders/jest/init-test-bed.mjs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@
99
// TODO(dgp1130): These imports likely don't resolve in stricter package environments like `pnpm`, since they are resolved relative to
1010
// `@angular-devkit/build-angular` rather than the user's workspace. Should look into virtual modules to support those use cases.
1111

12+
import { provideZoneChangeDetection, NgModule } from '@angular/core';
1213
import { getTestBed } from '@angular/core/testing';
1314
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
1415

15-
getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
16+
@NgModule({
17+
providers: [typeof window.Zone !== 'undefined' ? provideZoneChangeDetection() : []],
18+
})
19+
class TestModule {}
20+
21+
getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
1622
errorOnUnknownElements: true,
1723
errorOnUnknownProperties: true,
1824
});

packages/angular_devkit/build_angular/src/builders/karma/browser_builder.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,18 @@ async function initializeBrowser(
149149
return [karma, (await webpackConfigurationTransformer?.(config)) ?? config];
150150
}
151151

152-
function getBuiltInMainFile(): string {
152+
function getBuiltInMainFile(includeZoneProvider = false): string {
153153
const content = Buffer.from(
154154
`
155+
import { NgModule${includeZoneProvider ? ', provideZoneChangeDetection' : ''} } from '@angular/core';
155156
import { getTestBed } from '@angular/core/testing';
156157
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
157158
159+
@NgModule({providers: [${includeZoneProvider ? 'provideZoneChangeDetection(), ' : ''}]})
160+
export class TestModule {}
161+
158162
// Initialize the Angular testing environment.
159-
getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
163+
getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
160164
errorOnUnknownElements: true,
161165
errorOnUnknownProperties: true
162166
});

packages/angular_devkit/build_angular/src/builders/web-test-runner/jasmine_runner.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9+
import { NgModule } from '@angular/core';
910
import { getTestBed } from '@angular/core/testing';
1011
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
1112
import {
@@ -63,8 +64,13 @@ export async function runJasmineTests(jasmineEnv) {
6364
// eslint-disable-next-line no-undef
6465
jasmine.DEFAULT_TIMEOUT_INTERVAL = config.defaultTimeoutInterval;
6566

67+
@NgModule({
68+
providers: [typeof window.Zone !== 'undefined' ? provideZoneChangeDetection() : []],
69+
})
70+
class TestModule {}
71+
6672
// Initialize `TestBed` automatically for users. This assumes we already evaluated `zone.js/testing`.
67-
getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {
73+
getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
6874
errorOnUnknownElements: true,
6975
errorOnUnknownProperties: true,
7076
});

packages/schematics/angular/application/files/module-files/src/app/app-module.ts.template

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NgModule, provideBrowserGlobalErrorListeners<% if(zoneless) { %>, provideZonelessChangeDetection<% } %> } from '@angular/core';
1+
import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core';
22
import { BrowserModule } from '@angular/platform-browser';
33
<% if (routing) { %>
44
import { AppRoutingModule } from './app-routing-module';<% } %>
@@ -13,8 +13,7 @@ import { App } from './app';
1313
AppRoutingModule<% } %>
1414
],
1515
providers: [
16-
provideBrowserGlobalErrorListeners()<% if (zoneless) { %>,
17-
provideZonelessChangeDetection()<% } %>
16+
provideBrowserGlobalErrorListeners()
1817
],
1918
bootstrap: [App]
2019
})

packages/schematics/angular/application/files/module-files/src/app/app__suffix__.spec.ts.template

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
<% if(zoneless) { %>import { provideZonelessChangeDetection } from '@angular/core';
2-
<% } %>import { TestBed } from '@angular/core/testing';<% if (routing) { %>
1+
import { TestBed } from '@angular/core/testing';<% if (routing) { %>
32
import { RouterModule } from '@angular/router';<% } %>
43
import { App } from './app';
54

@@ -11,8 +10,7 @@ describe('App', () => {
1110
],<% } %>
1211
declarations: [
1312
App
14-
],<% if(zoneless) { %>
15-
providers: [provideZonelessChangeDetection()]<% } %>
13+
],
1614
}).compileComponents();
1715
});
1816

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { ApplicationConfig, provideBrowserGlobalErrorListeners, <% if(!zoneless) { %>provideZoneChangeDetection<% } else { %>provideZonelessChangeDetection<% } %> } from '@angular/core';<% if (routing) { %>
1+
import { ApplicationConfig, provideBrowserGlobalErrorListeners<% if(!zoneless) { %>, provideZoneChangeDetection<% } %> } from '@angular/core';<% if (routing) { %>
22
import { provideRouter } from '@angular/router';
33

44
import { routes } from './app.routes';<% } %>
55

66
export const appConfig: ApplicationConfig = {
77
providers: [
8-
provideBrowserGlobalErrorListeners(),
9-
<% if(zoneless) { %>provideZonelessChangeDetection()<% } else { %>provideZoneChangeDetection({ eventCoalescing: true })<% } %>,
8+
provideBrowserGlobalErrorListeners(),<% if(!zoneless) { %>
9+
provideZoneChangeDetection({ eventCoalescing: true }),<% } %>
1010
<% if (routing) {%>provideRouter(routes)<% } %>
1111
]
1212
};

packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.spec.ts.template

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
<% if(zoneless) { %>import { provideZonelessChangeDetection } from '@angular/core';
2-
<% } %>import { TestBed } from '@angular/core/testing';
1+
import { TestBed } from '@angular/core/testing';
32
import { App } from './app';
43

54
describe('App', () => {
65
beforeEach(async () => {
76
await TestBed.configureTestingModule({
8-
imports: [App],<% if(zoneless) { %>
9-
providers: [provideZonelessChangeDetection()]<% } %>
7+
imports: [App],
108
}).compileComponents();
119
});
1210

0 commit comments

Comments
 (0)