diff --git a/packages/angular_devkit/build_angular/src/builders/browser/index.ts b/packages/angular_devkit/build_angular/src/builders/browser/index.ts index 34f21b81543c..23c391a3608a 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/index.ts @@ -173,6 +173,19 @@ export function buildWebpackBrowser( // Check and warn about IE browser support checkInternetExplorerSupport(initialization.projectRoot, context.logger); + // Add index file to watched files. + if (options.watch) { + const indexInputFile = path.join(context.workspaceRoot, getIndexInputFile(options.index)); + initialization.config.plugins ??= []; + initialization.config.plugins.push({ + apply: (compiler: webpack.Compiler) => { + compiler.hooks.thisCompilation.tap('build-angular', (compilation) => { + compilation.fileDependencies.add(indexInputFile); + }); + }, + }); + } + return { ...initialization, cacheOptions: normalizeCacheOptions(projectMetadata, context.workspaceRoot), diff --git a/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/index_watch_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/index_watch_spec.ts new file mode 100644 index 000000000000..b023f6f3833f --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/index_watch_spec.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { concatMap, count, take, timeout } from 'rxjs/operators'; +import { BUILD_TIMEOUT, buildWebpackBrowser } from '../../index'; +import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup'; + +describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => { + describe('Behavior: "index is updated during watch mode"', () => { + it('index is watched in watch mode', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + watch: true, + }); + + const buildCount = await harness + .execute() + .pipe( + timeout(BUILD_TIMEOUT), + concatMap(async ({ result }, index) => { + expect(result?.success).toBe(true); + + switch (index) { + case 0: { + harness.expectFile('dist/index.html').content.toContain('HelloWorldApp'); + harness.expectFile('dist/index.html').content.not.toContain('UpdatedPageTitle'); + + // Trigger rebuild + await harness.modifyFile('src/index.html', (s) => + s.replace('HelloWorldApp', 'UpdatedPageTitle'), + ); + break; + } + case 1: { + harness.expectFile('dist/index.html').content.toContain('UpdatedPageTitle'); + break; + } + } + }), + take(2), + count(), + ) + .toPromise(); + + expect(buildCount).toBe(2); + }); + }); +});