From 9d29cbca0f0c04bb5998cc2cd15180456656ad7e Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Fri, 17 Feb 2017 01:17:15 +0000 Subject: [PATCH] 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`. --- docs/documentation/build.md | 2 +- docs/documentation/serve.md | 2 ++ packages/@angular/cli/commands/build.ts | 9 +++-- packages/@angular/cli/commands/e2e.ts | 6 ++++ packages/@angular/cli/commands/serve.ts | 6 ++++ packages/@angular/cli/models/build-options.ts | 1 + packages/@angular/cli/tasks/serve.ts | 13 ++++++++ packages/@ngtools/webpack/src/plugin.ts | 8 +++-- tests/e2e/tests/build/watch.ts | 33 +++++++++++++++++++ 9 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 tests/e2e/tests/build/watch.ts diff --git a/docs/documentation/build.md b/docs/documentation/build.md index 8dadcc293b49..cee14729c080 100644 --- a/docs/documentation/build.md +++ b/docs/documentation/build.md @@ -65,7 +65,7 @@ All builds make use of bundling, and using the `--prod` flag in `ng build --pro or `ng serve --prod` will also make use of uglifying and tree-shaking functionality. ## Options -`--watch` (`-w`) flag to run builds when files change +`--watch` (`-w`) rebuild when files change `--target` (`-t`) define the build target diff --git a/docs/documentation/serve.md b/docs/documentation/serve.md index eaf41d5eebf0..e7e46eee6490 100644 --- a/docs/documentation/serve.md +++ b/docs/documentation/serve.md @@ -6,6 +6,8 @@ `ng serve` builds the application and starts a web server ## Options +`--watch` (`-w`) rebuild when files change + `--port` (`-p`) port to serve the application on `--host` (`-H`) host where to listen diff --git a/packages/@angular/cli/commands/build.ts b/packages/@angular/cli/commands/build.ts index 0cc554268e08..eeb4163d849a 100644 --- a/packages/@angular/cli/commands/build.ts +++ b/packages/@angular/cli/commands/build.ts @@ -28,6 +28,7 @@ export const baseBuildCommandOptions: any = [ { name: 'i18n-format', type: String }, { name: 'locale', type: String }, { name: 'extract-css', type: Boolean, aliases: ['ec'] }, + { name: 'watch', type: Boolean, aliases: ['w'] }, { name: 'output-hashing', type: String, @@ -44,7 +45,6 @@ export const baseBuildCommandOptions: any = [ ]; export interface BuildTaskOptions extends BuildOptions { - watch?: boolean; statsJson?: boolean; } @@ -54,13 +54,18 @@ const BuildCommand = Command.extend({ aliases: ['b'], availableOptions: baseBuildCommandOptions.concat([ - { name: 'watch', type: Boolean, default: false, aliases: ['w'] }, { name: 'stats-json', type: Boolean, default: false } ]), run: function (commandOptions: BuildTaskOptions) { const project = this.project; + const additionalDefaults: any = { + watch: false + }; + + commandOptions = Object.assign({}, additionalDefaults, commandOptions); + // Check angular version. Version.assertAngularVersionIs2_3_1OrHigher(project.root); diff --git a/packages/@angular/cli/commands/e2e.ts b/packages/@angular/cli/commands/e2e.ts index 3a83bae4e832..80432b0ec236 100644 --- a/packages/@angular/cli/commands/e2e.ts +++ b/packages/@angular/cli/commands/e2e.ts @@ -32,6 +32,12 @@ const E2eCommand = Command.extend({ const E2eTask = require('../tasks/e2e').E2eTask; this.project.ngConfig = this.project.ngConfig || CliConfig.fromProject(); + const additionalDefaults: any = { + watch: false + }; + + commandOptions = Object.assign({}, additionalDefaults, commandOptions); + const e2eTask = new E2eTask({ ui: this.ui, project: this.project diff --git a/packages/@angular/cli/commands/serve.ts b/packages/@angular/cli/commands/serve.ts index f736ce16f1f8..5ddb9c36b770 100644 --- a/packages/@angular/cli/commands/serve.ts +++ b/packages/@angular/cli/commands/serve.ts @@ -97,6 +97,12 @@ const ServeCommand = Command.extend({ run: function (commandOptions: ServeTaskOptions) { const ServeTask = require('../tasks/serve').default; + const additionalDefaults: any = { + watch: true + }; + + commandOptions = Object.assign({}, additionalDefaults, commandOptions); + Version.assertAngularVersionIs2_3_1OrHigher(this.project.root); commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host; diff --git a/packages/@angular/cli/models/build-options.ts b/packages/@angular/cli/models/build-options.ts index e4e871e42b8d..919de64e2b13 100644 --- a/packages/@angular/cli/models/build-options.ts +++ b/packages/@angular/cli/models/build-options.ts @@ -13,6 +13,7 @@ export interface BuildOptions { i18nFormat?: string; locale?: string; extractCss?: boolean; + watch?: boolean; outputHashing?: string; poll?: number; } diff --git a/packages/@angular/cli/tasks/serve.ts b/packages/@angular/cli/tasks/serve.ts index 6cd7c3809448..8838266eef9b 100644 --- a/packages/@angular/cli/tasks/serve.ts +++ b/packages/@angular/cli/tasks/serve.ts @@ -68,6 +68,19 @@ export default Task.extend({ } if (!webpackConfig.entry.main) { webpackConfig.entry.main = []; } webpackConfig.entry.main.unshift(...entryPoints); + + if (!serveTaskOptions.watch) { + // There's no option to turn off file watching in webpack-dev-server, but + // we can override the file watcher instead. + webpackConfig.plugins.unshift({ + apply: (compiler: any) => { + compiler.plugin('after-environment', () => { + compiler.watchFileSystem = { watch: () => {} }; + }); + } + }); + } + webpackCompiler = webpack(webpackConfig); if (rebuildDoneCb) { diff --git a/packages/@ngtools/webpack/src/plugin.ts b/packages/@ngtools/webpack/src/plugin.ts index e26f9ab47a72..c6e824fcb08b 100644 --- a/packages/@ngtools/webpack/src/plugin.ts +++ b/packages/@ngtools/webpack/src/plugin.ts @@ -255,9 +255,11 @@ export class AotPlugin implements Tapable { this._firstRun = false; this._diagnoseFiles = {}; - compiler.watchFileSystem.watcher.once('aggregated', (changes: string[]) => { - changes.forEach((fileName: string) => this._compilerHost.invalidate(fileName)); - }); + if (compiler.watchFileSystem.watcher) { + compiler.watchFileSystem.watcher.once('aggregated', (changes: string[]) => { + changes.forEach((fileName: string) => this._compilerHost.invalidate(fileName)); + }); + } }); // Add lazy modules to the context module for @angular/core/src/linker diff --git a/tests/e2e/tests/build/watch.ts b/tests/e2e/tests/build/watch.ts new file mode 100644 index 000000000000..fef262b98c76 --- /dev/null +++ b/tests/e2e/tests/build/watch.ts @@ -0,0 +1,33 @@ +import { + killAllProcesses, + exec, + waitForAnyProcessOutputToMatch, + silentExecAndWaitForOutputToMatch +} from '../../utils/process'; +import { expectToFail } from '../../utils/utils'; + + +const webpackGoodRegEx = /webpack: bundle is now VALID|webpack: Compiled successfully./; + +export default function () { + if (process.platform.startsWith('win')) { + return Promise.resolve(); + } + + return silentExecAndWaitForOutputToMatch('ng', ['serve'], webpackGoodRegEx) + // Should trigger a rebuild. + .then(() => exec('touch', 'src/main.ts')) + .then(() => waitForAnyProcessOutputToMatch(webpackGoodRegEx, 5000)) + .then(() => killAllProcesses(), (err: any) => { + killAllProcesses(); + throw err; + }) + .then(() => silentExecAndWaitForOutputToMatch('ng', ['serve', '--no-watch'], webpackGoodRegEx)) + // Should not trigger a rebuild when not watching files. + .then(() => exec('touch', 'src/main.ts')) + .then(() => expectToFail(() => waitForAnyProcessOutputToMatch(webpackGoodRegEx, 5000))) + .then(() => killAllProcesses(), (err: any) => { + killAllProcesses(); + throw err; + }) +}