Angular组件内存泄漏 - 在Chrome和Microsoft Edge上(可能所有浏览器,但尚未测试所有浏览器)
- 我已经在最新版本的Angular 11、12和13上尝试了下面的应用程序,并且已经成功地使它们全部泄漏内存。
- 当销毁组件时,浏览器没有对Angular组件进行垃圾回收。
- 组件的浅大小(来自内存检查器)似乎很小,但保留大小(来自内存检查器)很大。
- DOM节点保留在内存中,导致显着的内存泄漏。
- 我已经能够让这个程序在Chrome和Edge中造成内存泄漏(尚未尝试其他浏览器)。
- 它在Angular的开发模式和生产模式下都会发生。
- 它可能与CSS属性display: flex有关。
- 我无法在stackblitz上重新创建这个泄漏。我只能在本地运行该应用程序的机器上使其工作。
有时它不会泄漏内存,有时会。这就是为什么这是我最近面临的最大难题之一。
请不要立即将此写成“我无法复制,所以一定是假的”,如果您首次运行以下程序并且它没有泄漏内存,请尝试几次。我发誓它最终会进入一种状态(因为这个bug困扰了我一段时间),导致它泄漏内存。
我已经将其缩小到这个简单的应用程序,因为这个内存泄漏一直在影响我正在工作的一个更大的生产应用程序。
下面是简化版本的应用程序,可用于测试。
https://github.com/kevinpbaker/angular-memory-killer
package.json
{
"name": "memory-killer",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --port 4201",
"build": "ng build --prod --aot --buildOptimizer --commonChunk --vendorChunk --optimization --progress",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~11.2.14",
"@angular/cdk": "^11.2.13",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/material": "^11.2.13",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular/router": "~11.2.14",
"rxjs": "~6.5.4",
"rxjs-compat": "^6.5.5",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.18",
"@angular/cli": "~11.2.18",
"@angular/compiler-cli": "~11.2.14",
"@angular/language-service": "~11.2.14",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~4.0.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.3.13",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.7.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "4.0.8"
}
}
app.module.ts
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AppComponent, MemoryKiller2Component, MemoryKillerComponent} from './app.component';
@NgModule({
declarations: [
AppComponent,
MemoryKillerComponent,
MemoryKiller2Component
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Memory Killer</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
app.component.ts
import {Component} from '@angular/core';
import {timer} from 'rxjs';
import {map} from 'rxjs/operators';
@Component({
selector: 'app-root',
template: '<app-memory-killer *ngIf="killCycle$|async"></app-memory-killer>',
})
export class AppComponent {
// change 1000 to 1 if you want to speed up the memory killer
killCycle$ = timer(0, 1000).pipe(map(k => k % 2 !== 0));
}
@Component({
selector: 'app-memory-killer',
template: `
<div class="memory-killer">
<app-memory-killer2></app-memory-killer2>
<app-memory-killer2></app-memory-killer2>
<app-memory-killer2></app-memory-killer2>
</div>
`,
styles: [`.memory-killer { display: flex; }`]
})
export class MemoryKillerComponent { }
@Component({
selector: 'app-memory-killer2',
template: `
<div class="memory-killer2">
<div>Killing your memory</div>
<div>Killing your memory</div>
<div>Killing your memory</div>
</div>
`,
styles: [`.memory-killer2 { display: flex; }`],
})
export class MemoryKiller2Component { }
Microsoft Edge 分离元素查看器和内存检查器 - 版本 97.0.1072.55
Chrome 内存检查器 - 版本 97.0.4692.99
DOM 节点上升的可视化 - 您可以大量手动进行垃圾回收,但不会回收组件
请问这是 Angular 的 bug 还是浏览器的 bug?还是您能指引我去寻找合适的人来解决这个问题?
这个问题是浏览器的 bug。由 Chromium 开发团队修复了。请参见“原始 Angular 问题帖子”中的最后一篇帖子。
原始 Angular 问题帖子:https://github.com/angular/angular/issues/45080
Chromium 的 bug 具体说明和修复:https://bugs.chromium.org/p/chromium/issues/detail?id=1308845