mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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
This commit is contained in:
committed by
Andrew Kushnir
parent
e941e6b80f
commit
dd2f53b9cd
@@ -102,6 +102,7 @@ export {
|
||||
HydrationInfo as ɵHydrationInfo,
|
||||
readHydrationInfo as ɵreadHydrationInfo,
|
||||
SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER,
|
||||
resetIncrementalHydrationEnabledWarnedForTests as ɵresetIncrementalHydrationEnabledWarnedForTests,
|
||||
} from './hydration/utils';
|
||||
export {
|
||||
CurrencyIndex as ɵCurrencyIndex,
|
||||
|
||||
@@ -52,7 +52,11 @@ import {
|
||||
trackTriggerForDebugging,
|
||||
} from './utils';
|
||||
import {DEHYDRATED_BLOCK_REGISTRY, DehydratedBlockRegistry} from './registry';
|
||||
import {assertIncrementalHydrationIsConfigured, assertSsrIdDefined} from '../hydration/utils';
|
||||
import {
|
||||
warnIncrementalHydrationNotConfigured,
|
||||
assertSsrIdDefined,
|
||||
isIncrementalHydrationEnabled,
|
||||
} from '../hydration/utils';
|
||||
import {ɵɵdeferEnableTimerScheduling, renderPlaceholder} from './rendering';
|
||||
|
||||
import {
|
||||
@@ -136,6 +140,7 @@ export function ɵɵdefer(
|
||||
const tNode = declareNoDirectiveHostTemplate(lView, tView, index, null, 0, 0);
|
||||
const injector = lView[INJECTOR];
|
||||
|
||||
const incrementalHydrationEnabled = isIncrementalHydrationEnabled(injector);
|
||||
if (tView.firstCreatePass) {
|
||||
performanceMarkFeature('NgDefer');
|
||||
|
||||
@@ -143,8 +148,8 @@ export function ɵɵdefer(
|
||||
if (typeof ngHmrMode !== 'undefined' && ngHmrMode) {
|
||||
logHmrWarning(injector);
|
||||
}
|
||||
if (hasHydrateTriggers(flags)) {
|
||||
assertIncrementalHydrationIsConfigured(injector);
|
||||
if (hasHydrateTriggers(flags) && !incrementalHydrationEnabled) {
|
||||
warnIncrementalHydrationNotConfigured();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +203,7 @@ export function ɵɵdefer(
|
||||
setLDeferBlockDetails(lView, adjustedIndex, lDetails);
|
||||
|
||||
let registry: DehydratedBlockRegistry | null = null;
|
||||
if (ssrUniqueId !== null) {
|
||||
if (ssrUniqueId !== null && incrementalHydrationEnabled) {
|
||||
// Store this defer block in the registry, to have an access to
|
||||
// internal data structures from hydration runtime code.
|
||||
registry = injector.get(DEHYDRATED_BLOCK_REGISTRY);
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
SerializedView,
|
||||
} from './interfaces';
|
||||
import {IS_INCREMENTAL_HYDRATION_ENABLED, JSACTION_BLOCK_ELEMENT_MAP} from './tokens';
|
||||
import {RuntimeError, RuntimeErrorCode} from '../errors';
|
||||
import {formatRuntimeError, RuntimeError, RuntimeErrorCode} from '../errors';
|
||||
import {DeferBlockTrigger, HydrateTriggerDetails} from '../defer/interfaces';
|
||||
import {hoverEventNames, interactionEventNames} from '../../primitives/defer/src/triggers';
|
||||
import {DEHYDRATED_BLOCK_REGISTRY} from '../defer/registry';
|
||||
@@ -411,15 +411,23 @@ export function isIncrementalHydrationEnabled(injector: Injector): boolean {
|
||||
});
|
||||
}
|
||||
|
||||
let incrementalHydrationEnabledWarned = false;
|
||||
export function resetIncrementalHydrationEnabledWarnedForTests() {
|
||||
incrementalHydrationEnabledWarned = false;
|
||||
}
|
||||
|
||||
/** Throws an error if the incremental hydration is not enabled */
|
||||
export function assertIncrementalHydrationIsConfigured(injector: Injector) {
|
||||
if (!isIncrementalHydrationEnabled(injector)) {
|
||||
throw new RuntimeError(
|
||||
RuntimeErrorCode.MISCONFIGURED_INCREMENTAL_HYDRATION,
|
||||
'Angular has detected that some `@defer` blocks use `hydrate` triggers, ' +
|
||||
'but incremental hydration was not enabled. Please ensure that the `withIncrementalHydration()` ' +
|
||||
'call is added as an argument for the `provideClientHydration()` function call ' +
|
||||
'in your application config.',
|
||||
export function warnIncrementalHydrationNotConfigured(): void {
|
||||
if (!incrementalHydrationEnabledWarned) {
|
||||
incrementalHydrationEnabledWarned = true;
|
||||
console.warn(
|
||||
formatRuntimeError(
|
||||
RuntimeErrorCode.MISCONFIGURED_INCREMENTAL_HYDRATION,
|
||||
'Angular has detected that some `@defer` blocks use `hydrate` triggers, ' +
|
||||
'but incremental hydration was not enabled. Please ensure that the `withIncrementalHydration()` ' +
|
||||
'call is added as an argument for the `provideClientHydration()` function call ' +
|
||||
'in your application config.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
ɵJSACTION_BLOCK_ELEMENT_MAP as JSACTION_BLOCK_ELEMENT_MAP,
|
||||
ɵJSACTION_EVENT_CONTRACT as JSACTION_EVENT_CONTRACT,
|
||||
ɵgetDocument as getDocument,
|
||||
ɵresetIncrementalHydrationEnabledWarnedForTests as resetIncrementalHydrationEnabledWarnedForTests,
|
||||
ɵTimerScheduler as TimerScheduler,
|
||||
provideZoneChangeDetection,
|
||||
} from '@angular/core';
|
||||
@@ -2870,7 +2871,7 @@ describe('platform-server partial hydration integration', () => {
|
||||
});
|
||||
|
||||
describe('misconfiguration', () => {
|
||||
it('should throw an error when `withIncrementalHydration()` is missing in SSR setup', async () => {
|
||||
it('should log a warning when `withIncrementalHydration()` is missing in SSR setup', async () => {
|
||||
@Component({
|
||||
selector: 'app',
|
||||
template: `
|
||||
@@ -2886,17 +2887,15 @@ describe('platform-server partial hydration integration', () => {
|
||||
|
||||
// Empty list, `withIncrementalHydration()` is not included intentionally.
|
||||
const hydrationFeatures = () => [];
|
||||
const consoleSpy = spyOn(console, 'warn');
|
||||
resetIncrementalHydrationEnabledWarnedForTests();
|
||||
|
||||
let producedError;
|
||||
try {
|
||||
await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures});
|
||||
} catch (error: unknown) {
|
||||
producedError = error;
|
||||
}
|
||||
expect((producedError as Error).message).toContain('NG0508');
|
||||
await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures});
|
||||
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(jasmine.stringMatching('NG0508'));
|
||||
});
|
||||
|
||||
it('should throw an error when `withIncrementalHydration()` is missing in hydration setup', async () => {
|
||||
it('should log a warning when `withIncrementalHydration()` is missing in hydration setup', async () => {
|
||||
@Component({
|
||||
selector: 'app',
|
||||
template: `
|
||||
@@ -2919,18 +2918,18 @@ describe('platform-server partial hydration integration', () => {
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
let producedError;
|
||||
try {
|
||||
const doc = getDocument();
|
||||
await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, {
|
||||
envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}],
|
||||
// Empty list, `withIncrementalHydration()` is not included intentionally.
|
||||
hydrationFeatures: () => [],
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
producedError = error;
|
||||
}
|
||||
expect((producedError as Error).message).toContain('NG0508');
|
||||
const consoleSpy = spyOn(console, 'warn');
|
||||
resetIncrementalHydrationEnabledWarnedForTests();
|
||||
|
||||
const doc = getDocument();
|
||||
await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, {
|
||||
envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}],
|
||||
// Empty list, `withIncrementalHydration()` is not included intentionally.
|
||||
hydrationFeatures: () => [],
|
||||
});
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(jasmine.stringMatching('NG0508'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user