Skip to content

Commit 9d29cbc

Browse files
filipesilvahansl
authored andcommitted
feat(@angular/cli): add watch flag to serve/e2e (#4749)
This is useful when you don't want the server to rebuild in the middle of something. A good example is when running e2e tests. Especially on larger suites, one would prefer to continue working while the build is tested without compromising tests. This will break tests on #4744. They should be adjusted to add the `--watch` flag since they depend on the live reload behaviour during `ng e2e`.
1 parent 121c390 commit 9d29cbc

File tree

9 files changed

+74
-6
lines changed

9 files changed

+74
-6
lines changed

docs/documentation/build.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ All builds make use of bundling, and using the `--prod` flag in `ng build --pro
6565
or `ng serve --prod` will also make use of uglifying and tree-shaking functionality.
6666

6767
## Options
68-
`--watch` (`-w`) flag to run builds when files change
68+
`--watch` (`-w`) rebuild when files change
6969

7070
`--target` (`-t`) define the build target
7171

docs/documentation/serve.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
`ng serve` builds the application and starts a web server
77

88
## Options
9+
`--watch` (`-w`) rebuild when files change
10+
911
`--port` (`-p`) port to serve the application on
1012

1113
`--host` (`-H`) host where to listen

packages/@angular/cli/commands/build.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export const baseBuildCommandOptions: any = [
2828
{ name: 'i18n-format', type: String },
2929
{ name: 'locale', type: String },
3030
{ name: 'extract-css', type: Boolean, aliases: ['ec'] },
31+
{ name: 'watch', type: Boolean, aliases: ['w'] },
3132
{
3233
name: 'output-hashing',
3334
type: String,
@@ -44,7 +45,6 @@ export const baseBuildCommandOptions: any = [
4445
];
4546

4647
export interface BuildTaskOptions extends BuildOptions {
47-
watch?: boolean;
4848
statsJson?: boolean;
4949
}
5050

@@ -54,13 +54,18 @@ const BuildCommand = Command.extend({
5454
aliases: ['b'],
5555

5656
availableOptions: baseBuildCommandOptions.concat([
57-
{ name: 'watch', type: Boolean, default: false, aliases: ['w'] },
5857
{ name: 'stats-json', type: Boolean, default: false }
5958
]),
6059

6160
run: function (commandOptions: BuildTaskOptions) {
6261
const project = this.project;
6362

63+
const additionalDefaults: any = {
64+
watch: false
65+
};
66+
67+
commandOptions = Object.assign({}, additionalDefaults, commandOptions);
68+
6469
// Check angular version.
6570
Version.assertAngularVersionIs2_3_1OrHigher(project.root);
6671

packages/@angular/cli/commands/e2e.ts

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ const E2eCommand = Command.extend({
3232
const E2eTask = require('../tasks/e2e').E2eTask;
3333
this.project.ngConfig = this.project.ngConfig || CliConfig.fromProject();
3434

35+
const additionalDefaults: any = {
36+
watch: false
37+
};
38+
39+
commandOptions = Object.assign({}, additionalDefaults, commandOptions);
40+
3541
const e2eTask = new E2eTask({
3642
ui: this.ui,
3743
project: this.project

packages/@angular/cli/commands/serve.ts

+6
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ const ServeCommand = Command.extend({
9797
run: function (commandOptions: ServeTaskOptions) {
9898
const ServeTask = require('../tasks/serve').default;
9999

100+
const additionalDefaults: any = {
101+
watch: true
102+
};
103+
104+
commandOptions = Object.assign({}, additionalDefaults, commandOptions);
105+
100106
Version.assertAngularVersionIs2_3_1OrHigher(this.project.root);
101107
commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host;
102108

packages/@angular/cli/models/build-options.ts

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface BuildOptions {
1313
i18nFormat?: string;
1414
locale?: string;
1515
extractCss?: boolean;
16+
watch?: boolean;
1617
outputHashing?: string;
1718
poll?: number;
1819
}

packages/@angular/cli/tasks/serve.ts

+13
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ export default Task.extend({
6868
}
6969
if (!webpackConfig.entry.main) { webpackConfig.entry.main = []; }
7070
webpackConfig.entry.main.unshift(...entryPoints);
71+
72+
if (!serveTaskOptions.watch) {
73+
// There's no option to turn off file watching in webpack-dev-server, but
74+
// we can override the file watcher instead.
75+
webpackConfig.plugins.unshift({
76+
apply: (compiler: any) => {
77+
compiler.plugin('after-environment', () => {
78+
compiler.watchFileSystem = { watch: () => {} };
79+
});
80+
}
81+
});
82+
}
83+
7184
webpackCompiler = webpack(webpackConfig);
7285

7386
if (rebuildDoneCb) {

packages/@ngtools/webpack/src/plugin.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,11 @@ export class AotPlugin implements Tapable {
255255
this._firstRun = false;
256256
this._diagnoseFiles = {};
257257

258-
compiler.watchFileSystem.watcher.once('aggregated', (changes: string[]) => {
259-
changes.forEach((fileName: string) => this._compilerHost.invalidate(fileName));
260-
});
258+
if (compiler.watchFileSystem.watcher) {
259+
compiler.watchFileSystem.watcher.once('aggregated', (changes: string[]) => {
260+
changes.forEach((fileName: string) => this._compilerHost.invalidate(fileName));
261+
});
262+
}
261263
});
262264

263265
// Add lazy modules to the context module for @angular/core/src/linker

tests/e2e/tests/build/watch.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {
2+
killAllProcesses,
3+
exec,
4+
waitForAnyProcessOutputToMatch,
5+
silentExecAndWaitForOutputToMatch
6+
} from '../../utils/process';
7+
import { expectToFail } from '../../utils/utils';
8+
9+
10+
const webpackGoodRegEx = /webpack: bundle is now VALID|webpack: Compiled successfully./;
11+
12+
export default function () {
13+
if (process.platform.startsWith('win')) {
14+
return Promise.resolve();
15+
}
16+
17+
return silentExecAndWaitForOutputToMatch('ng', ['serve'], webpackGoodRegEx)
18+
// Should trigger a rebuild.
19+
.then(() => exec('touch', 'src/main.ts'))
20+
.then(() => waitForAnyProcessOutputToMatch(webpackGoodRegEx, 5000))
21+
.then(() => killAllProcesses(), (err: any) => {
22+
killAllProcesses();
23+
throw err;
24+
})
25+
.then(() => silentExecAndWaitForOutputToMatch('ng', ['serve', '--no-watch'], webpackGoodRegEx))
26+
// Should not trigger a rebuild when not watching files.
27+
.then(() => exec('touch', 'src/main.ts'))
28+
.then(() => expectToFail(() => waitForAnyProcessOutputToMatch(webpackGoodRegEx, 5000)))
29+
.then(() => killAllProcesses(), (err: any) => {
30+
killAllProcesses();
31+
throw err;
32+
})
33+
}

0 commit comments

Comments
 (0)