Skip to content

Commit dd2f53b

Browse files
JeanMecheAndrewKushnir
authored andcommitted
refactor(core): warning when hydration trigger is used without hydration being enabled (#64185)
This replaces the error we were throwing before the change. This allows component with defer triggerrs to be used on both SSR'd and CSR. fixes #64184 PR Close #64185
1 parent e941e6b commit dd2f53b

File tree

4 files changed

+47
-34
lines changed

4 files changed

+47
-34
lines changed

packages/core/src/core_private_export.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export {
102102
HydrationInfo as ɵHydrationInfo,
103103
readHydrationInfo as ɵreadHydrationInfo,
104104
SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER,
105+
resetIncrementalHydrationEnabledWarnedForTests as ɵresetIncrementalHydrationEnabledWarnedForTests,
105106
} from './hydration/utils';
106107
export {
107108
CurrencyIndex as ɵCurrencyIndex,

packages/core/src/defer/instructions.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ import {
5252
trackTriggerForDebugging,
5353
} from './utils';
5454
import {DEHYDRATED_BLOCK_REGISTRY, DehydratedBlockRegistry} from './registry';
55-
import {assertIncrementalHydrationIsConfigured, assertSsrIdDefined} from '../hydration/utils';
55+
import {
56+
warnIncrementalHydrationNotConfigured,
57+
assertSsrIdDefined,
58+
isIncrementalHydrationEnabled,
59+
} from '../hydration/utils';
5660
import {ɵɵdeferEnableTimerScheduling, renderPlaceholder} from './rendering';
5761

5862
import {
@@ -136,15 +140,16 @@ export function ɵɵdefer(
136140
const tNode = declareNoDirectiveHostTemplate(lView, tView, index, null, 0, 0);
137141
const injector = lView[INJECTOR];
138142

143+
const incrementalHydrationEnabled = isIncrementalHydrationEnabled(injector);
139144
if (tView.firstCreatePass) {
140145
performanceMarkFeature('NgDefer');
141146

142147
if (ngDevMode) {
143148
if (typeof ngHmrMode !== 'undefined' && ngHmrMode) {
144149
logHmrWarning(injector);
145150
}
146-
if (hasHydrateTriggers(flags)) {
147-
assertIncrementalHydrationIsConfigured(injector);
151+
if (hasHydrateTriggers(flags) && !incrementalHydrationEnabled) {
152+
warnIncrementalHydrationNotConfigured();
148153
}
149154
}
150155

@@ -198,7 +203,7 @@ export function ɵɵdefer(
198203
setLDeferBlockDetails(lView, adjustedIndex, lDetails);
199204

200205
let registry: DehydratedBlockRegistry | null = null;
201-
if (ssrUniqueId !== null) {
206+
if (ssrUniqueId !== null && incrementalHydrationEnabled) {
202207
// Store this defer block in the registry, to have an access to
203208
// internal data structures from hydration runtime code.
204209
registry = injector.get(DEHYDRATED_BLOCK_REGISTRY);

packages/core/src/hydration/utils.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
SerializedView,
3535
} from './interfaces';
3636
import {IS_INCREMENTAL_HYDRATION_ENABLED, JSACTION_BLOCK_ELEMENT_MAP} from './tokens';
37-
import {RuntimeError, RuntimeErrorCode} from '../errors';
37+
import {formatRuntimeError, RuntimeError, RuntimeErrorCode} from '../errors';
3838
import {DeferBlockTrigger, HydrateTriggerDetails} from '../defer/interfaces';
3939
import {hoverEventNames, interactionEventNames} from '../../primitives/defer/src/triggers';
4040
import {DEHYDRATED_BLOCK_REGISTRY} from '../defer/registry';
@@ -411,15 +411,23 @@ export function isIncrementalHydrationEnabled(injector: Injector): boolean {
411411
});
412412
}
413413

414+
let incrementalHydrationEnabledWarned = false;
415+
export function resetIncrementalHydrationEnabledWarnedForTests() {
416+
incrementalHydrationEnabledWarned = false;
417+
}
418+
414419
/** Throws an error if the incremental hydration is not enabled */
415-
export function assertIncrementalHydrationIsConfigured(injector: Injector) {
416-
if (!isIncrementalHydrationEnabled(injector)) {
417-
throw new RuntimeError(
418-
RuntimeErrorCode.MISCONFIGURED_INCREMENTAL_HYDRATION,
419-
'Angular has detected that some `@defer` blocks use `hydrate` triggers, ' +
420-
'but incremental hydration was not enabled. Please ensure that the `withIncrementalHydration()` ' +
421-
'call is added as an argument for the `provideClientHydration()` function call ' +
422-
'in your application config.',
420+
export function warnIncrementalHydrationNotConfigured(): void {
421+
if (!incrementalHydrationEnabledWarned) {
422+
incrementalHydrationEnabledWarned = true;
423+
console.warn(
424+
formatRuntimeError(
425+
RuntimeErrorCode.MISCONFIGURED_INCREMENTAL_HYDRATION,
426+
'Angular has detected that some `@defer` blocks use `hydrate` triggers, ' +
427+
'but incremental hydration was not enabled. Please ensure that the `withIncrementalHydration()` ' +
428+
'call is added as an argument for the `provideClientHydration()` function call ' +
429+
'in your application config.',
430+
),
423431
);
424432
}
425433
}

packages/platform-server/test/incremental_hydration_spec.ts

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
ɵJSACTION_BLOCK_ELEMENT_MAP as JSACTION_BLOCK_ELEMENT_MAP,
2525
ɵJSACTION_EVENT_CONTRACT as JSACTION_EVENT_CONTRACT,
2626
ɵgetDocument as getDocument,
27+
ɵresetIncrementalHydrationEnabledWarnedForTests as resetIncrementalHydrationEnabledWarnedForTests,
2728
ɵTimerScheduler as TimerScheduler,
2829
provideZoneChangeDetection,
2930
} from '@angular/core';
@@ -2870,7 +2871,7 @@ describe('platform-server partial hydration integration', () => {
28702871
});
28712872

28722873
describe('misconfiguration', () => {
2873-
it('should throw an error when `withIncrementalHydration()` is missing in SSR setup', async () => {
2874+
it('should log a warning when `withIncrementalHydration()` is missing in SSR setup', async () => {
28742875
@Component({
28752876
selector: 'app',
28762877
template: `
@@ -2886,17 +2887,15 @@ describe('platform-server partial hydration integration', () => {
28862887

28872888
// Empty list, `withIncrementalHydration()` is not included intentionally.
28882889
const hydrationFeatures = () => [];
2890+
const consoleSpy = spyOn(console, 'warn');
2891+
resetIncrementalHydrationEnabledWarnedForTests();
28892892

2890-
let producedError;
2891-
try {
2892-
await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures});
2893-
} catch (error: unknown) {
2894-
producedError = error;
2895-
}
2896-
expect((producedError as Error).message).toContain('NG0508');
2893+
await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures});
2894+
expect(consoleSpy).toHaveBeenCalledTimes(1);
2895+
expect(consoleSpy).toHaveBeenCalledWith(jasmine.stringMatching('NG0508'));
28972896
});
28982897

2899-
it('should throw an error when `withIncrementalHydration()` is missing in hydration setup', async () => {
2898+
it('should log a warning when `withIncrementalHydration()` is missing in hydration setup', async () => {
29002899
@Component({
29012900
selector: 'app',
29022901
template: `
@@ -2919,18 +2918,18 @@ describe('platform-server partial hydration integration', () => {
29192918

29202919
////////////////////////////////
29212920

2922-
let producedError;
2923-
try {
2924-
const doc = getDocument();
2925-
await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, {
2926-
envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}],
2927-
// Empty list, `withIncrementalHydration()` is not included intentionally.
2928-
hydrationFeatures: () => [],
2929-
});
2930-
} catch (error: unknown) {
2931-
producedError = error;
2932-
}
2933-
expect((producedError as Error).message).toContain('NG0508');
2921+
const consoleSpy = spyOn(console, 'warn');
2922+
resetIncrementalHydrationEnabledWarnedForTests();
2923+
2924+
const doc = getDocument();
2925+
await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, {
2926+
envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}],
2927+
// Empty list, `withIncrementalHydration()` is not included intentionally.
2928+
hydrationFeatures: () => [],
2929+
});
2930+
2931+
expect(consoleSpy).toHaveBeenCalledTimes(1);
2932+
expect(consoleSpy).toHaveBeenCalledWith(jasmine.stringMatching('NG0508'));
29342933
});
29352934
});
29362935
});

0 commit comments

Comments
 (0)