Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1a2767a

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 a60de9b commit 1a2767a

File tree

21 files changed

+87
-85
lines changed

21 files changed

+87
-85
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,14 +436,18 @@ async function initializeApplication(
436436
externalDependencies: options.externalDependencies,
437437
};
438438

439+
const usesZoneJS = buildOptions.polyfills.includes('zone.js');
439440
const virtualTestBedInit = createVirtualModulePlugin({
440441
namespace: 'angular:test-bed-init',
441442
loadContent: async () => {
442443
const contents: string[] = [
443444
// Initialize the Angular testing environment
445+
`import { NgModule${usesZoneJS ? ', provideZoneChangeDetection' : ''} } from '@angular/core';`,
444446
`import { getTestBed } from '@angular/core/testing';`,
445447
`import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';`,
446-
`getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting(), {`,
448+
`@NgModule({ providers: [${usesZoneJS ? 'provideZoneChangeDetection(), ' : ''}], })`,
449+
`export class TestModule {}`,
450+
`getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {`,
447451
` errorOnUnknownElements: true,`,
448452
` errorOnUnknownProperties: true,`,
449453
'});',

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ import { OutputHashing } from '../../../application/schema';
1313
import { NormalizedUnitTestBuilderOptions, injectTestingPolyfills } from '../../options';
1414
import { findTests, getTestEntrypoints } from '../../test-discovery';
1515
import { RunnerOptions } from '../api';
16+
import { u } from 'tar';
1617

1718
function createTestBedInitVirtualFile(
1819
providersFile: string | undefined,
1920
projectSourceRoot: string,
21+
polyfills: string[] = [],
2022
): string {
23+
const usesZoneJS = polyfills.includes('zone.js');
2124
let providersImport = 'const providers = [];';
2225
if (providersFile) {
2326
const relativePath = path.relative(projectSourceRoot, providersFile);
@@ -28,15 +31,15 @@ function createTestBedInitVirtualFile(
2831

2932
return `
3033
// Initialize the Angular testing environment
31-
import { NgModule } from '@angular/core';
34+
import { NgModule${usesZoneJS ? ', provideZoneChangeDetection' : ''} } from '@angular/core';
3235
import { getTestBed, ɵgetCleanupHook as getCleanupHook } from '@angular/core/testing';
3336
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
3437
${providersImport}
3538
// Same as https://github.com/angular/angular/blob/05a03d3f975771bb59c7eefd37c01fa127ee2229/packages/core/testing/srcs/test_hooks.ts#L21-L29
3639
beforeEach(getCleanupHook(false));
3740
afterEach(getCleanupHook(true));
3841
@NgModule({
39-
providers,
42+
providers: [${usesZoneJS ? 'provideZoneChangeDetection(), ' : ''}...providers],
4043
})
4144
export class TestModule {}
4245
getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
@@ -113,7 +116,11 @@ export async function getVitestBuildOptions(
113116

114117
buildOptions.polyfills = injectTestingPolyfills(buildOptions.polyfills);
115118

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

118125
return {
119126
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

‎packages/schematics/angular/application/index_spec.ts

Lines changed: 5 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ describe('Application Schematic', () => {
296296
expect(pkg.devDependencies['less']).toEqual(latestVersions['less']);
297297
});
298298

299-
it('should include zone.js if "zoneless" option is not present', async () => {
299+
it('should _not_ include zone.js if "zoneless" option is not present', async () => {
300300
const tree = await schematicRunner.runSchematic(
301301
'application',
302302
{
@@ -307,7 +307,7 @@ describe('Application Schematic', () => {
307307
);
308308

309309
const pkg = JSON.parse(tree.readContent('/package.json'));
310-
expect(pkg.dependencies['zone.js']).toEqual(latestVersions['zone.js']);
310+
expect(pkg.dependencies['zone.js']).toBeUndefined();
311311
});
312312

313313
it('should not include zone.js if "zoneless" option is true', async () => {
@@ -800,7 +800,7 @@ describe('Application Schematic', () => {
800800
);
801801
});
802802

803-
it('should add provideZonelessChangeDetection() in app-module.ts when zoneless is true', async () => {
803+
it('should not add provideZonelessChangeDetection() in app-module.ts when zoneless is true', async () => {
804804
const tree = await schematicRunner.runSchematic(
805805
'application',
806806
{
@@ -812,53 +812,10 @@ describe('Application Schematic', () => {
812812
);
813813
const path = '/projects/foo/src/app/app-module.ts';
814814
const fileContent = tree.readContent(path);
815-
expect(fileContent).toContain('provideZonelessChangeDetection()');
816-
});
817-
818-
it('should not add provideZonelessChangeDetection() in app-module.ts when zoneless is false', async () => {
819-
const tree = await schematicRunner.runSchematic(
820-
'application',
821-
{
822-
...defaultOptions,
823-
zoneless: false,
824-
standalone: false,
825-
},
826-
workspaceTree,
827-
);
828-
const path = '/projects/foo/src/app/app-module.ts';
829-
const fileContent = tree.readContent(path);
830-
expect(fileContent).not.toContain('provideZonelessChangeDetection()');
831-
});
832-
833-
it('should add provideZonelessChangeDetection() when zoneless is true', async () => {
834-
const tree = await schematicRunner.runSchematic(
835-
'application',
836-
{
837-
...defaultOptions,
838-
zoneless: true,
839-
},
840-
workspaceTree,
841-
);
842-
const path = '/projects/foo/src/app/app.config.ts';
843-
const fileContent = tree.readContent(path);
844-
expect(fileContent).toContain('provideZonelessChangeDetection()');
845-
});
846-
847-
it('should not add provideZonelessChangeDetection() when zoneless is false', async () => {
848-
const tree = await schematicRunner.runSchematic(
849-
'application',
850-
{
851-
...defaultOptions,
852-
zoneless: false,
853-
},
854-
workspaceTree,
855-
);
856-
const path = '/projects/foo/src/app/app.config.ts';
857-
const fileContent = tree.readContent(path);
858815
expect(fileContent).not.toContain('provideZonelessChangeDetection()');
859816
});
860817

861-
it('should not add provideZoneChangeDetection when zoneless is true', async () => {
818+
it('should not add any change detection provider when zoneless is true', async () => {
862819
const tree = await schematicRunner.runSchematic(
863820
'application',
864821
{
@@ -869,7 +826,7 @@ describe('Application Schematic', () => {
869826
);
870827
const path = '/projects/foo/src/app/app.config.ts';
871828
const fileContent = tree.readContent(path);
872-
expect(fileContent).not.toContain('provideZoneChangeDetection');
829+
expect(fileContent).not.toMatch(/provideZone(less)?ChangeDetection/gi);
873830
});
874831
});
875832

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /