@@ -218,6 +218,8 @@ export async function* serveWithVite(
218218 }
219219
220220 let needClientUpdate = true ;
221+ const componentUpdateIds : string [ ] = [ ] ;
222+
221223 switch ( result . kind ) {
222224 case ResultKind . Full :
223225 if ( result . detail ?. [ 'htmlIndexPath' ] ) {
@@ -250,11 +252,6 @@ export async function* serveWithVite(
250252 ) ;
251253 }
252254
253- // Invalidate SSR module graph to ensure that only new rebuild is used and not stale component updates
254- if ( server && browserOptions . ssr && templateUpdates . size > 0 ) {
255- server . moduleGraph . invalidateAll ( ) ;
256- }
257-
258255 // Clear stale template updates on code rebuilds
259256 templateUpdates . clear ( ) ;
260257
@@ -302,28 +299,14 @@ export async function* serveWithVite(
302299 server ,
303300 'Builder must provide an initial full build before component update results.' ,
304301 ) ;
305-
306- // Invalidate SSR module graph to ensure that new component updates are used
307- // TODO: Use fine-grained invalidation of only the component update modules
308- if ( browserOptions . ssr ) {
309- server . moduleGraph . invalidateAll ( ) ;
310- const { ɵresetCompiledComponents } = ( await server . ssrLoadModule ( '/main.server.mjs' ) ) as {
311- ɵresetCompiledComponents : ( ) => void ;
312- } ;
313- ɵresetCompiledComponents ( ) ;
314- }
315-
316302 for ( const componentUpdate of result . updates ) {
317303 if ( componentUpdate . type === 'template' ) {
304+ componentUpdateIds . push ( componentUpdate . id ) ;
318305 templateUpdates . set ( componentUpdate . id , componentUpdate . content ) ;
319- server . ws . send ( 'angular:component-update' , {
320- id : componentUpdate . id ,
321- timestamp : Date . now ( ) ,
322- } ) ;
323306 }
324307 }
325- context . logger . info ( 'Component update sent to client(s).' ) ;
326- continue ;
308+
309+ break ;
327310 default :
328311 context . logger . warn ( `Unknown result kind [${ ( result as Result ) . kind } ] provided by build.` ) ;
329312 continue ;
@@ -367,17 +350,17 @@ export async function* serveWithVite(
367350 ] ) ,
368351 ] ;
369352
370- if ( needClientUpdate ) {
371- await handleUpdate (
372- normalizePath ,
373- generatedFiles ,
374- assetFiles ,
375- server ,
376- serverOptions ,
377- context . logger ,
378- componentStyles ,
379- ) ;
380- }
353+ await handleUpdate (
354+ normalizePath ,
355+ generatedFiles ,
356+ assetFiles ,
357+ server ,
358+ serverOptions ,
359+ context . logger ,
360+ componentStyles ,
361+ componentUpdateIds ,
362+ needClientUpdate ,
363+ ) ;
381364 } else {
382365 const projectName = context . target ?. project ;
383366 if ( ! projectName ) {
@@ -491,6 +474,8 @@ async function handleUpdate(
491474 serverOptions : NormalizedDevServerOptions ,
492475 logger : BuilderContext [ 'logger' ] ,
493476 componentStyles : Map < string , ComponentStyleRecord > ,
477+ componentUpdateIds : string [ ] ,
478+ needClientUpdate : boolean ,
494479) : Promise < void > {
495480 const updatedFiles : string [ ] = [ ] ;
496481
@@ -531,16 +516,30 @@ async function handleUpdate(
531516 updatedModules ?. forEach ( ( m ) => server . moduleGraph . invalidateModule ( m ) ) ;
532517 }
533518
534- if ( ! updatedFiles . length ) {
519+ if ( ! needClientUpdate ) {
535520 return ;
536521 }
537522
538- if ( destroyAngularServerAppCalled ) {
539- // Trigger module evaluation before reload to initiate dependency optimization.
540- await server . ssrLoadModule ( '/main.server.mjs' ) ;
523+ if ( ! updatedFiles . length && ! componentUpdateIds . length ) {
524+ return ;
541525 }
542526
543527 if ( serverOptions . hmr ) {
528+ if ( componentUpdateIds . length ) {
529+ for ( const id of componentUpdateIds ) {
530+ server . ws . send ( 'angular:component-update' , {
531+ id,
532+ timestamp : Date . now ( ) ,
533+ } ) ;
534+ }
535+
536+ logger . info ( 'Component update sent to client(s).' ) ;
537+ }
538+
539+ if ( ! updatedFiles . length ) {
540+ return ;
541+ }
542+
544543 if ( updatedFiles . every ( ( f ) => f . endsWith ( '.css' ) ) ) {
545544 let requiresReload = false ;
546545 const timestamp = Date . now ( ) ;
@@ -595,6 +594,11 @@ async function handleUpdate(
595594 // Clear used component tracking on full reload
596595 componentStyles . forEach ( ( record ) => record . used ?. clear ( ) ) ;
597596
597+ if ( destroyAngularServerAppCalled ) {
598+ // Trigger module evaluation before reload to initiate dependency optimization.
599+ await server . ssrLoadModule ( '/main.server.mjs' ) ;
600+ }
601+
598602 server . ws . send ( {
599603 type : 'full-reload' ,
600604 path : '*' ,
0 commit comments