-
Notifications
You must be signed in to change notification settings - Fork 27k
Open
Labels
area: coreIssues related to the framework runtimeIssues related to the framework runtimecore: event dispatchmemory leakIssue related to a memory leakIssue related to a memory leak
Milestone
Description
Which @angular/* package(s) are the source of the bug?
Don't known / other
Is this a regression?
No
Description
It appears that elements are not being garbage collected in an SSR application if:
- A child component contains an
output()which it's parent is using - A component is using a
@HostListener
How to reproduce in provided minimal sample
- Either start the dev server or run a production build (both have the same result)
- Open the app
- Open dev tools
- Click the toggle button multiple times
- Take a snapshot of the heap
- You now see multiple detached instances of both components which are still held in memory even though not used anymore
Validation
- Remove
@HostListenerfromWithHostListenercomponent// Change this @HostListener('click', ['$event']) public onClick(event: MouseEvent): void {} // to this public onClick(event: MouseEvent): void {}
- Remove
WithOutputcomponent's output listener fromAppcomponent<!-- change this --> <app-with-output (myOutput)="doSomething()"></app-with-output> <!-- to this --> <app-with-output></app-with-output>
- Run the app
- Click the toggle button multiple times
- Take a heap snapshot
- Now you can see that the DOM Nodes are cleaned up correctly
Changing the WithHostListener component to cleaning up the click listener manually (as seen in the snippet below) also enables the GC to cleanup the app-with-host-listener nodes.
import { Component, ElementRef, inject, OnDestroy, Renderer2 } from '@angular/core';
@Component({
selector: 'app-with-host-listener',
template: `
<div>With HostListener</div>
`,
})
export class WithHostListener implements OnDestroy {
private readonly renderer = inject(Renderer2);
private cleanupListener: (() => void) | undefined;
private readonly el = inject(ElementRef);
constructor() {
this.cleanupListener = this.renderer.listen(this.el.nativeElement, 'click', event => {
this.onClick(event);
});
}
public onClick(event: MouseEvent): void {console.log(event)}
ngOnDestroy(): void {
if (this.cleanupListener) {
this.cleanupListener();
}
}
}Please provide a link to a minimal reproduction of the bug
https://github.com/mii-shell/angular-dom-nodes-memory-leak
Please provide the exception or error you saw
No exception/error was thrown
Please provide the environment you discovered this bug in (run ng version)
Angular CLI : 21.0.5
Angular : 21.1.0-rc.0
Node.js : 24.4.1
Package Manager : npm 11.4.2
Operating System : linux x64
┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/build │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/cli │ 21.0.5 │ ^21.0.5 │
│ @angular/common │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/compiler │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/compiler-cli │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/core │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/forms │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/platform-browser │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/platform-server │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/router │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ @angular/ssr │ 21.1.0-rc.0 │ ^21.1.0-rc.0 │
│ rxjs │ 7.8.2 │ ~7.8.0 │
│ typescript │ 5.9.3 │ ~5.9.2 │
│ vitest │ 4.0.17 │ ^4.0.8 │
└───────────────────────────┴───────────────────┴───────────────────┘
Anything else?
- I originally thought this problem might be related to Event replay memory leak #59261, which is why I've used Angular version
21.1.0-rc.0in my minimal reproduction (which is the version in which this was fixed according to the changelog). Unfortunately, it did not resolve the issue. - I've also tested it with version 21.0.5, which resulted in the same
- Manual garbage collection does not remove the elements from the heap either
- Identical issue, regardless of whether
@HostListenerorhostoption in@Componentis used - This issue does not occur in a basic Angular app setup without SSR
TwentyFourMinutes, davidroth, MeAkib, SkyZeroZx, stefangrasboeck and 4 more
Metadata
Metadata
Assignees
Labels
area: coreIssues related to the framework runtimeIssues related to the framework runtimecore: event dispatchmemory leakIssue related to a memory leakIssue related to a memory leak