From 939d1612add13bab9aed6cc77bce0e17555bfe3b Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:42:57 -0500 Subject: [PATCH] fix(@angular/build): perform incremental background file updates with component updates When HMR is enabled, a change to a lazy route component template may alter the names of lazy chunks. These lazy chunks must be updated within the development server so that any later non-HMR based update will have access to these chunks. To support this, the incremental results from the build process can now emit background file updates that will provide output file changes without triggering client updates. (cherry picked from commit e59946ca329cc53b2eec1a64a597d14c3f04c975) --- .../src/builders/application/build-action.ts | 14 +++++------ .../build/src/builders/application/results.ts | 1 + .../src/builders/dev-server/vite-server.ts | 24 ++++++++++++------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/angular/build/src/builders/application/build-action.ts b/packages/angular/build/src/builders/application/build-action.ts index 4d3120da10f4..8fdfa1a9d5bc 100644 --- a/packages/angular/build/src/builders/application/build-action.ts +++ b/packages/angular/build/src/builders/application/build-action.ts @@ -264,6 +264,8 @@ function* emitOutputResults( const incrementalResult: IncrementalResult = { kind: ResultKind.Incremental, warnings: warnings as ResultMessage[], + // These files need to be updated in the dev server but should not signal any updates + background: hasTemplateUpdates, added: [], removed: [], modified: [], @@ -281,13 +283,6 @@ function* emitOutputResults( for (const file of outputFiles) { removedOutputFiles.delete(file.path); - // Temporarily ignore JS files until Angular compiler plugin refactor to allow - // bypassing application code bundling for template affecting only changes. - // TODO: Remove once refactor is complete. - if (hasTemplateUpdates && /\.js(?:\.map)?$/.test(file.path)) { - continue; - } - const previousHash = previousOutputInfo.get(file.path)?.hash; let needFile = false; if (previousHash === undefined) { @@ -299,6 +294,11 @@ function* emitOutputResults( } if (needFile) { + // Updates to non-JS files must signal an update with the dev server + if (!/(?:\.js|\.map)?$/.test(file.path)) { + incrementalResult.background = false; + } + incrementalResult.files[file.path] = { type: file.type, contents: file.contents, diff --git a/packages/angular/build/src/builders/application/results.ts b/packages/angular/build/src/builders/application/results.ts index 077237967425..3e3f0dd99315 100644 --- a/packages/angular/build/src/builders/application/results.ts +++ b/packages/angular/build/src/builders/application/results.ts @@ -36,6 +36,7 @@ export interface FullResult extends BaseResult { export interface IncrementalResult extends BaseResult { kind: ResultKind.Incremental; + background?: boolean; added: string[]; removed: { path: string; type: BuildOutputFileType }[]; modified: string[]; diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index 439cebda2b03..78bb603fd933 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -217,6 +217,7 @@ export async function* serveWithVite( }); } + let needClientUpdate = true; switch (result.kind) { case ResultKind.Full: if (result.detail?.['htmlIndexPath']) { @@ -261,6 +262,9 @@ export async function* serveWithVite( case ResultKind.Incremental: assert(server, 'Builder must provide an initial full build before incremental results.'); + // Background updates should only update server files/options + needClientUpdate = !result.background; + for (const removed of result.removed) { const filePath = '/' + normalizePath(removed.path); generatedFiles.delete(filePath); @@ -363,15 +367,17 @@ export async function* serveWithVite( ]), ]; - await handleUpdate( - normalizePath, - generatedFiles, - assetFiles, - server, - serverOptions, - context.logger, - componentStyles, - ); + if (needClientUpdate) { + await handleUpdate( + normalizePath, + generatedFiles, + assetFiles, + server, + serverOptions, + context.logger, + componentStyles, + ); + } } else { const projectName = context.target?.project; if (!projectName) {