-
Notifications
You must be signed in to change notification settings - Fork 27.1k
SSG: when hydrating Angular renders contradicting state in @if-else, @switch, [ngSwitch], *ngTemplateOutlet #60218
Copy link
Copy link
Closed
Labels
area: coreIssues related to the framework runtimeIssues related to the framework runtimebugcore: hydration
Milestone
Description
Which @angular/* package(s) are the source of the bug?
Don't known / other
Is this a regression?
Yes
Description
When hydrating a prerendered page (SSG) and there are differences in states, Angular displays both the content that was pre-rendered and the live content at the same time, resulting in duplicated content which impacts very negatively UX and CWV metrics (like CLS).
@Component({
selector: 'app-demo',
template: `
<div> <!-- for a short while both A and B will be visible, when app becomes stable A will disappear -->
@if (variant === 'A') {
<span>A</span>
} @else {
<span>B</span>
}
</div>
<div> <!-- for a short while both A and B will be visible, when app becomes stable A will disappear -->
@switch (variant) {
@case('A') { <span>A</span> }
@case('B') { <span>B</span> }
}
</div>
<div><!-- for a short while both A and B will be visible, when app becomes stable A will disappear -->
<ng-container [ngSwitch]="variant">
<span *ngSwithCase="A">A</span>
<span *ngSwithCase="B">B</span>
</ng-container>
</div>
<div><!-- for a short while both A and B will be visible, when app becomes stable A will disappear -->
<ng-container *ngTemplateOutlet="variant === 'A' ? templateA : templateB" />
<ng-template #templateA>
<span>A</span>
</ng-template>
<ng-template #templateB>
<span>B</span>
</ng-template>
</div>
<div><!-- this will work fine, only A or B will be visible at any time -->
<ng-container *ngIf="variant === 'A'; else templateB">
<span>A</span>
</ng-container>
<ng-template #templateB>
<span>B</span>
</ng-template>
</div>
`,
imports: [CommonModule],
})
export class DemoComponent implements OnInit {
private readonly platformId = inject(PLATFORM_ID);
variant = 'A';
ngOnInit(): void {
// simulating different state, in the browser than it was in the server
// IRL, this could be any state change: user permissions, authentication, query parameters, etc.
if (isPlatformBrowser(this.platformId)) {
this.variant = 'B';
}
}
}Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No error
Please provide the environment you discovered this bug in (run ng version)
Angular CLI: 19.2.0
Node: 22.7.0
Package Manager: npm 10.8.2
OS: win32 x64
Angular: 19.2.0
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, platform-server, router, ssr
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1902.0
@angular-devkit/build-angular 19.2.0
@angular-devkit/core 19.2.0
@angular-devkit/schematics 19.2.0
@angular/cdk 19.2.1
@schematics/angular 19.0.6
ng-packagr 19.0.1
rxjs 7.8.2
typescript 5.6.3
zone.js 0.15.0
Anything else?
This is a duplicate for a 58670 issue (which is now closed but the bug is still present), the 58670 has some live examples.
This issue seems to be related to "withI18nSupport" hydration option even though none of the elements has i18n properties on them.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area: coreIssues related to the framework runtimeIssues related to the framework runtimebugcore: hydration