Skip to content

Commit ee45227

Browse files
committed
feat(@angular/cli): add watch flag to serve/e2e
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 angular#4744. They should be adjusted to add the `--watch` flag since they depend on the live reload behaviour during `ng e2e`.
1 parent a22474e commit ee45227

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
@@ -65,6 +65,19 @@ export default Task.extend({
6565
}
6666
if (!webpackConfig.entry.main) { webpackConfig.entry.main = []; }
6767
webpackConfig.entry.main.unshift(...entryPoints);
68+
69+
if (!serveTaskOptions.watch) {
70+
// There's no option to turn off file watching in webpack-dev-server, but
71+
// we can override the file watcher instead.
72+
webpackConfig.plugins.unshift({
73+
apply: (compiler: any) => {
74+
compiler.plugin('after-environment', () => {
75+
compiler.watchFileSystem = { watch: () => {} };
76+
});
77+
}
78+
});
79+
}
80+
6881
webpackCompiler = webpack(webpackConfig);
6982

7083
if (rebuildDoneCb) {

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,11 @@ export class AotPlugin implements Tapable {
242242
this._firstRun = false;
243243
this._diagnoseFiles = {};
244244

245-
compiler.watchFileSystem.watcher.once('aggregated', (changes: string[]) => {
246-
changes.forEach((fileName: string) => this._compilerHost.invalidate(fileName));
247-
});
245+
if (compiler.watchFileSystem.watcher) {
246+
compiler.watchFileSystem.watcher.once('aggregated', (changes: string[]) => {
247+
changes.forEach((fileName: string) => this._compilerHost.invalidate(fileName));
248+
});
249+
}
248250
});
249251

250252
// 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)