Skip to content

Commit

Permalink
feat(@schematics/angular): add option to setup new workspace or appli…
Browse files Browse the repository at this point in the history
…cation as zoneless mode
  • Loading branch information
aparzi authored and jkrems committed Oct 15, 2024
1 parent 5f473af commit 755f3a0
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TestBed } from '@angular/core/testing';<% if (routing) { %>
<% if(experimentalZoneless) { %> import { provideExperimentalZonelessChangeDetection } from '@angular/core'; <% } %>import { TestBed } from '@angular/core/testing';<% if (routing) { %>
import { RouterModule } from '@angular/router';<% } %>
import { AppComponent } from './app.component';

Expand All @@ -11,6 +11,7 @@ describe('AppComponent', () => {
declarations: [
AppComponent
],
<% if(experimentalZoneless) { %>providers: [provideExperimentalZonelessChangeDetection()]<% } %>
}).compileComponents();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule } from '@angular/core';
import { NgModule<% if(experimentalZoneless) { %>, provideExperimentalZonelessChangeDetection<% } %> } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
<% if (routing) { %>
import { AppRoutingModule } from './app-routing.module';<% } %>
Expand All @@ -12,7 +12,7 @@ import { AppComponent } from './app.component';
BrowserModule<% if (routing) { %>,
AppRoutingModule<% } %>
],
providers: [],
providers: [<% if (experimentalZoneless) { %>provideExperimentalZonelessChangeDetection()<% } %>],
bootstrap: [AppComponent]
})
export class AppModule { }
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<% if(!!viewEncapsulation) { %>import { ViewEncapsulation } from '@angular/core';
<% }%>import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule, {
ngZoneEventCoalescing: true<% if(!!viewEncapsulation) { %>,
<% if(!experimentalZoneless) { %>ngZoneEventCoalescing: true,<% } %><% if(!!viewEncapsulation) { %>
defaultEncapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } %>
})
.catch(err => console.error(err));
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<% if(experimentalZoneless) { %> import { provideExperimentalZonelessChangeDetection } from '@angular/core'; <% } %>
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
<% if(experimentalZoneless) { %>providers: [provideExperimentalZonelessChangeDetection()]<% } %>
}).compileComponents();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';<% if (routing) { %>
import { ApplicationConfig, <% if(!experimentalZoneless) { %>provideZoneChangeDetection<% } else { %>provideExperimentalZonelessChangeDetection<% } %> } from '@angular/core';<% if (routing) { %>
import { provideRouter } from '@angular/router';

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

export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true })<% if (routing) { %>, provideRouter(routes)<% } %>]
providers: [
<% if(experimentalZoneless) { %>provideExperimentalZonelessChangeDetection()<% } else { %>provideZoneChangeDetection({ eventCoalescing: true })<% } %><% if (routing) {%>, provideRouter(routes)<% } %>
]
};
4 changes: 2 additions & 2 deletions packages/schematics/angular/application/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ function addAppToWorkspaceFile(
outputPath: `dist/${folderName}`,
index: `${sourceRoot}/index.html`,
browser: `${sourceRoot}/main.ts`,
polyfills: ['zone.js'],
polyfills: options.experimentalZoneless ? [] : ['zone.js'],
tsConfig: `${projectRoot}tsconfig.app.json`,
inlineStyleLanguage,
assets: [{ 'glob': '**/*', 'input': `${projectRoot}public` }],
Expand Down Expand Up @@ -279,7 +279,7 @@ function addAppToWorkspaceFile(
: {
builder: Builders.Karma,
options: {
polyfills: ['zone.js', 'zone.js/testing'],
polyfills: options.experimentalZoneless ? [] : ['zone.js', 'zone.js/testing'],
tsConfig: `${projectRoot}tsconfig.spec.json`,
inlineStyleLanguage,
assets: [{ 'glob': '**/*', 'input': `${projectRoot}public` }],
Expand Down
72 changes: 72 additions & 0 deletions packages/schematics/angular/application/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -698,5 +698,77 @@ describe('Application Schematic', () => {
}),
);
});

it('should add provideExperimentalZonelessChangeDetection() in app.module.ts when experimentalZoneless is true', async () => {
const tree = await schematicRunner.runSchematic(
'application',
{
...defaultOptions,
experimentalZoneless: true,
standalone: false,
},
workspaceTree,
);
const path = '/projects/foo/src/app/app.module.ts';
const fileContent = tree.readContent(path);
expect(fileContent).toContain('provideExperimentalZonelessChangeDetection()');
});

it('should not add provideExperimentalZonelessChangeDetection() in app.module.ts when experimentalZoneless is false', async () => {
const tree = await schematicRunner.runSchematic(
'application',
{
...defaultOptions,
experimentalZoneless: false,
standalone: false,
},
workspaceTree,
);
const path = '/projects/foo/src/app/app.module.ts';
const fileContent = tree.readContent(path);
expect(fileContent).not.toContain('provideExperimentalZonelessChangeDetection()');
});

it('should add provideExperimentalZonelessChangeDetection() when experimentalZoneless is true', async () => {
const tree = await schematicRunner.runSchematic(
'application',
{
...defaultOptions,
experimentalZoneless: true,
},
workspaceTree,
);
const path = '/projects/foo/src/app/app.config.ts';
const fileContent = tree.readContent(path);
expect(fileContent).toContain('provideExperimentalZonelessChangeDetection()');
});

it('should not add provideExperimentalZonelessChangeDetection() when experimentalZoneless is false', async () => {
const tree = await schematicRunner.runSchematic(
'application',
{
...defaultOptions,
experimentalZoneless: false,
},
workspaceTree,
);
const path = '/projects/foo/src/app/app.config.ts';
const fileContent = tree.readContent(path);
expect(fileContent).not.toContain('provideExperimentalZonelessChangeDetection()');
});

it('should not add provideZoneChangeDetection when experimentalZoneless is true', async () => {
const tree = await schematicRunner.runSchematic(
'application',
{
...defaultOptions,
experimentalZoneless: true,
},
workspaceTree,
);
const path = '/projects/foo/src/app/app.config.ts';
const fileContent = tree.readContent(path);
expect(fileContent).not.toContain('provideZoneChangeDetection');
});
});
});
5 changes: 5 additions & 0 deletions packages/schematics/angular/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@
"type": "boolean",
"default": false,
"x-user-analytics": "ep.ng_ssr"
},
"experimentalZoneless": {
"description": "Create an application that does not utilize zone.js.",
"type": "boolean",
"default": false
}
},
"required": ["name"]
Expand Down
1 change: 1 addition & 0 deletions packages/schematics/angular/ng-new/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default function (options: NgNewOptions): Rule {
minimal: options.minimal,
standalone: options.standalone,
ssr: options.ssr,
experimentalZoneless: options.experimentalZoneless,
};

return chain([
Expand Down
5 changes: 5 additions & 0 deletions packages/schematics/angular/ng-new/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@
"description": "Creates an application with Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) enabled.",
"type": "boolean",
"x-user-analytics": "ep.ng_ssr"
},
"experimentalZoneless": {
"description": "Create an application that does not utilize zone.js.",
"type": "boolean",
"default": false
}
},
"required": ["name", "version"]
Expand Down
2 changes: 1 addition & 1 deletion packages/schematics/angular/service-worker/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ describe('Service Worker Schematic', () => {
provideServiceWorker('ngsw-worker.js', {
enabled: !isDevMode(),
registrationStrategy: 'registerWhenStable:30000'
})
})
`);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ng } from '../../../utils/process';
import { useCIChrome } from '../../../utils/project';

export default async function () {
await ng('generate', 'app', 'standalone', '--experimental-zoneless', '--standalone');
await useCIChrome('standalone', 'projects/standalone');
await ng('test', 'standalone', '--watch=false');
await ng('build', 'standalone');

await ng(
'generate',
'app',
'ngmodules',
'--experimental-zoneless',
'--no-standalone',
'--skip-install',
);
await useCIChrome('ngmodules', 'projects/ngmodules');
await ng('test', 'ngmodules', '--watch=false');
await ng('build', 'ngmodules');
}

0 comments on commit 755f3a0

Please sign in to comment.