@@ -122,11 +122,19 @@ export const DEFER_BLOCK_CONFIG = new InjectionToken<DeferBlockConfig>(
122122) ;
123123
124124/**
125- * Determines whether defer blocks should be fully rendered through on the server side
126- * for incremental hydration.
125+ * Determines whether "hydrate" triggers should be activated. Triggers are activated in the following cases:
126+ * - on the server, when incremental hydration is enabled, to trigger the block and render the main content
127+ * - on the client for blocks that were server-side rendered, to start hydration process
127128 */
128- function shouldTriggerWhenOnServer ( injector : Injector ) {
129- return ! isPlatformBrowser ( injector ) && isIncrementalHydrationEnabled ( injector ) ;
129+ function shouldActivateHydrateTrigger ( lView : LView , tNode : TNode ) : boolean {
130+ const lDetails = getLDeferBlockDetails ( lView , tNode ) ;
131+ const injector = lView [ INJECTOR ] ! ;
132+ // TODO(incremental-hydration): ideally, this check should only happen once and then stored on
133+ // LDeferBlockDetails as a flag. This would make subsequent lookups very cheap.
134+ return (
135+ isIncrementalHydrationEnabled ( injector ) &&
136+ ( ! isPlatformBrowser ( injector ) || lDetails [ SSR_UNIQUE_ID ] !== null )
137+ ) ;
130138}
131139
132140// TODO(incremental-hydration): Optimize this further by moving the calculation to earlier
@@ -347,9 +355,6 @@ export function ɵɵdeferWhen(rawValue: unknown) {
347355 renderedState === DeferBlockState . Placeholder ) &&
348356 shouldTriggerWhenOnClient ( lView [ INJECTOR ] ! , lDetails , tDetails )
349357 ) {
350- // The `when` condition has changed to `true`, trigger defer block loading
351- // if the block is either in initial (nothing is rendered) or a placeholder
352- // state.
353358 triggerDeferBlock ( lView , tNode ) ;
354359 }
355360 } finally {
@@ -392,18 +397,22 @@ export function ɵɵdeferPrefetchWhen(rawValue: unknown) {
392397 */
393398export function ɵɵdeferHydrateWhen ( rawValue : unknown ) {
394399 const lView = getLView ( ) ;
400+ const tNode = getSelectedTNode ( ) ;
401+
402+ if ( ! shouldActivateHydrateTrigger ( lView , tNode ) ) {
403+ return ;
404+ }
395405
396406 // TODO(incremental-hydration): audit all defer instructions to reduce unnecessary work by
397407 // moving function calls inside their relevant control flow blocks
398408 const bindingIndex = nextBindingIndex ( ) ;
399- const tNode = getSelectedTNode ( ) ;
400409 const tView = getTView ( ) ;
401410 const hydrateTriggers = getHydrateTriggers ( tView , tNode ) ;
402411 hydrateTriggers . set ( DeferBlockTrigger . When , null ) ;
403412
404413 if ( bindingUpdated ( lView , bindingIndex , rawValue ) ) {
405414 const injector = lView [ INJECTOR ] ! ;
406- if ( shouldTriggerWhenOnServer ( injector ) ) {
415+ if ( ! isPlatformBrowser ( injector ) ) {
407416 // We are on the server and SSR for defer blocks is enabled.
408417 triggerDeferBlock ( lView , tNode ) ;
409418 } else {
@@ -434,12 +443,14 @@ export function ɵɵdeferHydrateWhen(rawValue: unknown) {
434443export function ɵɵdeferHydrateNever ( ) {
435444 const lView = getLView ( ) ;
436445 const tNode = getCurrentTNode ( ) ! ;
437- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
438- hydrateTriggers . set ( DeferBlockTrigger . Never , null ) ;
446+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
447+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
448+ hydrateTriggers . set ( DeferBlockTrigger . Never , null ) ;
439449
440- if ( shouldTriggerWhenOnServer ( lView [ INJECTOR ] ! ) ) {
441- // We are on the server and SSR for defer blocks is enabled.
442- triggerDeferBlock ( lView , tNode ) ;
450+ if ( ! isPlatformBrowser ( lView [ INJECTOR ] ! ) ) {
451+ // We are on the server and SSR for defer blocks is enabled.
452+ triggerDeferBlock ( lView , tNode ) ;
453+ }
443454 }
444455}
445456
@@ -466,14 +477,16 @@ export function ɵɵdeferPrefetchOnIdle() {
466477export function ɵɵdeferHydrateOnIdle ( ) {
467478 const lView = getLView ( ) ;
468479 const tNode = getCurrentTNode ( ) ! ;
469- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
470- hydrateTriggers . set ( DeferBlockTrigger . Idle , null ) ;
480+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
481+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
482+ hydrateTriggers . set ( DeferBlockTrigger . Idle , null ) ;
471483
472- if ( shouldTriggerWhenOnServer ( lView [ INJECTOR ] ! ) ) {
473- // We are on the server and SSR for defer blocks is enabled.
474- triggerDeferBlock ( lView , tNode ) ;
475- } else {
476- scheduleDelayedHydrating ( onIdle , lView , tNode ) ;
484+ if ( ! isPlatformBrowser ( lView [ INJECTOR ] ! ) ) {
485+ // We are on the server and SSR for defer blocks is enabled.
486+ triggerDeferBlock ( lView , tNode ) ;
487+ } else {
488+ scheduleDelayedHydrating ( onIdle , lView , tNode ) ;
489+ }
477490 }
478491}
479492
@@ -524,22 +537,26 @@ export function ɵɵdeferPrefetchOnImmediate() {
524537export function ɵɵdeferHydrateOnImmediate ( ) {
525538 const lView = getLView ( ) ;
526539 const tNode = getCurrentTNode ( ) ! ;
527- const injector = lView [ INJECTOR ] ! ;
528- const lDetails = getLDeferBlockDetails ( lView , tNode ) ;
529- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
530- hydrateTriggers . set ( DeferBlockTrigger . Immediate , null ) ;
540+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
541+ const injector = lView [ INJECTOR ] ! ;
542+ const lDetails = getLDeferBlockDetails ( lView , tNode ) ;
543+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
544+ hydrateTriggers . set ( DeferBlockTrigger . Immediate , null ) ;
531545
532- if ( shouldTriggerWhenOnServer ( injector ) ) {
533- triggerDeferBlock ( lView , tNode ) ;
534- } else {
535- incrementallyHydrateFromBlockName (
536- injector ,
537- lDetails [ SSR_UNIQUE_ID ] ! ,
538- ( deferBlock : DeferBlock ) => triggerAndWaitForCompletion ( deferBlock ) ,
539- ) ;
546+ if ( ! isPlatformBrowser ( injector ) ) {
547+ triggerDeferBlock ( lView , tNode ) ;
548+ } else {
549+ // TODO(incremental-hydration): see if we can resolve the circular dep issue
550+ // that required passing cleanup fns via the 3rd param here. Ideally we could
551+ // move the `triggerAndWaitForCompletion` call to a better location.
552+ incrementallyHydrateFromBlockName (
553+ injector ,
554+ lDetails [ SSR_UNIQUE_ID ] ! ,
555+ ( deferBlock : DeferBlock ) => triggerAndWaitForCompletion ( deferBlock ) ,
556+ ) ;
557+ }
540558 }
541559}
542-
543560/**
544561 * Creates runtime data structures for the `on timer` deferred trigger.
545562 * @param delay Amount of time to wait before loading the content.
@@ -566,14 +583,16 @@ export function ɵɵdeferPrefetchOnTimer(delay: number) {
566583export function ɵɵdeferHydrateOnTimer ( delay : number ) {
567584 const lView = getLView ( ) ;
568585 const tNode = getCurrentTNode ( ) ! ;
569- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
570- hydrateTriggers . set ( DeferBlockTrigger . Timer , delay ) ;
586+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
587+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
588+ hydrateTriggers . set ( DeferBlockTrigger . Timer , delay ) ;
571589
572- if ( shouldTriggerWhenOnServer ( lView [ INJECTOR ] ! ) ) {
573- // We are on the server and SSR for defer blocks is enabled.
574- triggerDeferBlock ( lView , tNode ) ;
575- } else {
576- scheduleDelayedHydrating ( onTimer ( delay ) , lView , tNode ) ;
590+ if ( ! isPlatformBrowser ( lView [ INJECTOR ] ! ) ) {
591+ // We are on the server and SSR for defer blocks is enabled.
592+ triggerDeferBlock ( lView , tNode ) ;
593+ } else {
594+ scheduleDelayedHydrating ( onTimer ( delay ) , lView , tNode ) ;
595+ }
577596 }
578597}
579598
@@ -636,12 +655,14 @@ export function ɵɵdeferPrefetchOnHover(triggerIndex: number, walkUpTimes?: num
636655export function ɵɵdeferHydrateOnHover ( ) {
637656 const lView = getLView ( ) ;
638657 const tNode = getCurrentTNode ( ) ! ;
639- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
640- hydrateTriggers . set ( DeferBlockTrigger . Hover , null ) ;
658+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
659+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
660+ hydrateTriggers . set ( DeferBlockTrigger . Hover , null ) ;
641661
642- if ( shouldTriggerWhenOnServer ( lView [ INJECTOR ] ! ) ) {
643- // We are on the server and SSR for defer blocks is enabled.
644- triggerDeferBlock ( lView , tNode ) ;
662+ if ( ! isPlatformBrowser ( lView [ INJECTOR ] ! ) ) {
663+ // We are on the server and SSR for defer blocks is enabled.
664+ triggerDeferBlock ( lView , tNode ) ;
665+ }
645666 }
646667 // The actual triggering of hydration on hover is handled by JSAction in
647668 // event_replay.ts.
@@ -706,12 +727,14 @@ export function ɵɵdeferPrefetchOnInteraction(triggerIndex: number, walkUpTimes
706727export function ɵɵdeferHydrateOnInteraction ( ) {
707728 const lView = getLView ( ) ;
708729 const tNode = getCurrentTNode ( ) ! ;
709- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
710- hydrateTriggers . set ( DeferBlockTrigger . Interaction , null ) ;
730+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
731+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
732+ hydrateTriggers . set ( DeferBlockTrigger . Interaction , null ) ;
711733
712- if ( shouldTriggerWhenOnServer ( lView [ INJECTOR ] ! ) ) {
713- // We are on the server and SSR for defer blocks is enabled.
714- triggerDeferBlock ( lView , tNode ) ;
734+ if ( ! isPlatformBrowser ( lView [ INJECTOR ] ! ) ) {
735+ // We are on the server and SSR for defer blocks is enabled.
736+ triggerDeferBlock ( lView , tNode ) ;
737+ }
715738 }
716739 // The actual triggering of hydration on interaction is handled by JSAction in
717740 // event_replay.ts.
@@ -776,13 +799,15 @@ export function ɵɵdeferPrefetchOnViewport(triggerIndex: number, walkUpTimes?:
776799export function ɵɵdeferHydrateOnViewport ( ) {
777800 const lView = getLView ( ) ;
778801 const tNode = getCurrentTNode ( ) ! ;
779- const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
780- hydrateTriggers . set ( DeferBlockTrigger . Viewport , null ) ;
781- const injector = lView [ INJECTOR ] ! ;
802+ if ( shouldActivateHydrateTrigger ( lView , tNode ) ) {
803+ const hydrateTriggers = getHydrateTriggers ( getTView ( ) , tNode ) ;
804+ hydrateTriggers . set ( DeferBlockTrigger . Viewport , null ) ;
805+ const injector = lView [ INJECTOR ] ! ;
782806
783- if ( shouldTriggerWhenOnServer ( injector ) ) {
784- // We are on the server and SSR for defer blocks is enabled.
785- triggerDeferBlock ( lView , tNode ) ;
807+ if ( ! isPlatformBrowser ( injector ) ) {
808+ // We are on the server and SSR for defer blocks is enabled.
809+ triggerDeferBlock ( lView , tNode ) ;
810+ }
786811 }
787812 // The actual triggering of hydration on viewport happens in incremental.ts,
788813 // since these instructions won't exist for dehydrated content.
0 commit comments