Skip to content

Commit c2cbc19

Browse files
committed
feat(@schematics/angular): add option to setup new workspace or application as zoneless mode
Introduces option `--experimental-zoneless` to setup workspace or application as zoneless mode.
1 parent c0b76e3 commit c2cbc19

File tree

8 files changed

+42
-3
lines changed

8 files changed

+42
-3
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { AppModule } from './app/app.module';
55

66
platformBrowserDynamic().bootstrapModule(AppModule, {
7+
<% if(experimentalZoneless) { %>providers: [provideExperimentalZonelessChangeDetection()],<% } %>
78
ngZoneEventCoalescing: true<% if(!!viewEncapsulation) { %>,
89
defaultEncapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } %>
910
})

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ import { provideRouter } from '@angular/router';
44
import { routes } from './app.routes';<% } %>
55

66
export const appConfig: ApplicationConfig = {
7-
providers: [provideZoneChangeDetection({ eventCoalescing: true })<% if (routing) { %>, provideRouter(routes)<% } %>]
7+
providers: [
8+
<% if(experimentalZoneless) { %>provideExperimentalZonelessChangeDetection(),<% } %>
9+
provideZoneChangeDetection({ eventCoalescing: true })<% if (routing) { %>, provideRouter(routes)<% } %>
10+
]
811
};

packages/schematics/angular/application/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ function addAppToWorkspaceFile(
239239
outputPath: `dist/${folderName}`,
240240
index: `${sourceRoot}/index.html`,
241241
browser: `${sourceRoot}/main.ts`,
242-
polyfills: ['zone.js'],
242+
polyfills: options.experimentalZoneless ? [] : ['zone.js'],
243243
tsConfig: `${projectRoot}tsconfig.app.json`,
244244
inlineStyleLanguage,
245245
assets: [{ 'glob': '**/*', 'input': `${projectRoot}public` }],
@@ -279,7 +279,7 @@ function addAppToWorkspaceFile(
279279
: {
280280
builder: Builders.Karma,
281281
options: {
282-
polyfills: ['zone.js', 'zone.js/testing'],
282+
polyfills: options.experimentalZoneless ? [] : ['zone.js', 'zone.js/testing'],
283283
tsConfig: `${projectRoot}tsconfig.spec.json`,
284284
inlineStyleLanguage,
285285
assets: [{ 'glob': '**/*', 'input': `${projectRoot}public` }],

packages/schematics/angular/application/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@
117117
"type": "boolean",
118118
"default": false,
119119
"x-user-analytics": "ep.ng_ssr"
120+
},
121+
"experimentalZoneless": {
122+
"description": "Create an application that does not utilize zone.js.",
123+
"type": "boolean",
124+
"default": false
120125
}
121126
},
122127
"required": ["name"]

packages/schematics/angular/ng-new/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export default function (options: NgNewOptions): Rule {
3939
minimal: options.minimal,
4040
strict: options.strict,
4141
packageManager: options.packageManager,
42+
experimentalZoneless: options.experimentalZoneless,
4243
};
4344
const applicationOptions: ApplicationOptions = {
4445
projectRoot: '',
@@ -57,6 +58,7 @@ export default function (options: NgNewOptions): Rule {
5758
minimal: options.minimal,
5859
standalone: options.standalone,
5960
ssr: options.ssr,
61+
experimentalZoneless: options.experimentalZoneless,
6062
};
6163

6264
return chain([

packages/schematics/angular/ng-new/index_spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,22 @@ describe('Ng New Schematic', () => {
103103
const { cli } = JSON.parse(tree.readContent('/bar/angular.json'));
104104
expect(cli.packageManager).toBe('npm');
105105
});
106+
107+
it('should experimentalZoneless is set to true and add provideExperimentalZonelessChangeDetection in app.config', async () => {
108+
const tree = await schematicRunner.runSchematic('ng-new', {
109+
...defaultOptions,
110+
experimentalZoneless: true,
111+
});
112+
const fileContent = tree.readContent('/bar/src/app/app.config.ts');
113+
expect(fileContent).toContain('provideExperimentalZonelessChangeDetection()');
114+
});
115+
116+
it('should experimentalZoneless is set to false', async () => {
117+
const tree = await schematicRunner.runSchematic('ng-new', {
118+
...defaultOptions,
119+
experimentalZoneless: false,
120+
});
121+
const fileContent = tree.readContent('/bar/src/app/app.config.ts');
122+
expect(fileContent).not.toMatch('provideExperimentalZonelessChangeDetection()');
123+
});
106124
});

packages/schematics/angular/ng-new/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@
138138
"description": "Creates an application with Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) enabled.",
139139
"type": "boolean",
140140
"x-user-analytics": "ep.ng_ssr"
141+
},
142+
"experimentalZoneless": {
143+
"description": "Create an application that does not utilize zone.js.",
144+
"type": "boolean",
145+
"default": false
141146
}
142147
},
143148
"required": ["name", "version"]

packages/schematics/angular/workspace/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
"description": "The package manager used to install dependencies.",
4242
"type": "string",
4343
"enum": ["npm", "yarn", "pnpm", "cnpm", "bun"]
44+
},
45+
"experimentalZoneless": {
46+
"description": "Create an application without dependencies related to zone.js (zoneless)",
47+
"type": "boolean",
48+
"default": false
4449
}
4550
},
4651
"required": ["name", "version"]

0 commit comments

Comments
 (0)