You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular升级后@ng-bootstrap手风琴无限重渲染引发调用栈溢出问题

问题背景

我最近将Angular项目从v11升级到v12,同步将@ng-bootstrap/ng-bootstrap从v6升级到v10。升级过程没有需要大幅调整的改动,但后续遇到了Bootstrap手风琴组件的异常问题:页面上的手风琴持续重渲染,最终触发最大调用栈报错。

问题定位

已确认触发问题的具体版本是仅包含动画相关bug修复的8.0.3版本,对应修复日志如下:

animations: don't reflow in 'ngbRunTransition' (#3962) (f699999), closes #3954 #3952
animations: make sure 'ngbRunTransition' runs inside the zone (#3957) (a006a62), closes #3950
carousel: respect [animation]="false" (#3964) (9afae34), closes #3961

异常表现

页面加载完成后立即抛出如下错误,报错后仍可正常和手风琴组件交互:

zone.js:182 Uncaught RangeError: Maximum call stack size exceeded
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:191)
    at SafeSubscriber.next (Subscriber.js:122)
    at Subscriber._next (Subscriber.js:72)
    at Subscriber.next (Subscriber.js:49)
    at EventEmitter_.next (Subject.js:39)
    at EventEmitter_.emit (core.js:25935)
    at checkStable (core.js:28594)
    at onLeave (core.js:28722)
    at Object.onInvoke (core.js:28678)
    at ZoneDelegate.invoke (zone.js:371)

错误表现会根据手风琴内的面板数量呈现不同特征:

  • 1-3个面板:报错后可正常操作手风琴,无其他异常
  • 4个面板:报错后前2个面板渲染正常,第3个面板空白、第4个面板未渲染;点击任意面板后第4个面板会渲染完成可正常操作,仅第3个面板保持空白不可点击
  • 5个面板:报错后可正常操作手风琴,无其他异常
  • 6个面板:手风琴完全不渲染,仅在HTML中残留2个面板结构,对应代码如下:
<ngb-accordion _ngcontent-serverapp-c144="" role="tablist" activeids="acc-event_description" class="accordion" ng-reflect-active-ids="acc-event_description" aria-multiselectable="true"><!--container--><div><div role="tab"><!--container--></div><!--container--></div><div><div role="tab"><!--container--></div><!--container--></div><!--bindings={
  "ng-reflect-ng-for-of": "[object Object],[object Object"
}--></ngb-accordion>

另有一个异常现象:页面上其他元素更新时,会触发手风琴多次更新,该行为在版本升级前就已经存在。

排查情况

已完成以下排查操作:

  • 验证过开发/生产构建、Angular Universal(SSR)环境下该错误表现完全一致
  • 不给面板设置id可避免报错,但点击面板时组件会极速连续重渲染,自动分配的id快速递增,1秒内即可超过100,且手风琴完全无法使用,点击仅会更新id
  • 尝试设置[animation]="false"无任何效果
  • 分别尝试导入NgbModule、单独导入NgbAccordionModule均无改善
  • 尝试将手风琴组件单独作为模块加载排除其他代码影响,问题仍然复现

尝试使用Angular调试工具排查,但工具无法在页面加载时自动启动,来不及捕获性能分析数据。单独搭建的相同实现示例项目运行完全正常,说明是本项目内的某些因素触发了该问题,但暂时无法定位原因。
目前唯一能规避问题的方式是在HTML中硬编码面板,但实际场景下面板是动态获取的无法硬编码;在组件内硬编码面板(和示例项目逻辑一致)仍然会报错。

依赖及配置参考

项目依赖无明显版本不匹配问题,运行ng update提示所有依赖均符合版本要求,核心依赖如下:

"dependencies": {
  "@angular/animations": "~12.2.5",
  "@angular/common": "~12.2.5",
  "@angular/compiler": "~12.2.5",
  "@angular/core": "~12.2.5",
  "@angular/forms": "~12.2.5",
  "@angular/localize": "~12.2.5",
  "@angular/platform-browser": "~12.2.5",
  "@angular/platform-browser-dynamic": "~12.2.5",
  "@angular/platform-server": "~12.2.5",
  "@angular/router": "~12.2.5",
  "@auth0/angular-jwt": "^5.0.2",
  "@bugsnag/js": "^7.4.0",
  "@bugsnag/plugin-angular": "^7.4.0",
  "@ng-bootstrap/ng-bootstrap": "^10.0.0",
  "@nguniversal/express-engine": "^12.1.0",
  "@techiediaries/ngx-qrcode": "^9.1.0",
  "@types/url-parse": "^1.4.3",
  "bootstrap": "^4.5.0",
  "core-js": "^3.17.3",
  "express": "^4.17.1",
  "hammerjs": "^2.0.8",
  "jquery": "^3.3.1",
  "less": "4.1.1",
  "lodash": "^4.17.21",
  "logrocket": "^1.0.3",
  "moment": "^2.24.0",
  "ngx-barcode": "^0.3.0",
  "ngx-connection-service": "^7.0.3",
  "ngx-cookie": "^5.0.2",
  "ngx-cookie-backend": "^5.0.2",
  "popper.js": "^1.14.7",
  "rxjs": "~6.6.7",
  "sanitize-html": "^2.5.0",
  "tslib": "^2.3.1",
  "url-parse": "^1.4.7",
  "zone.js": "~0.11.4"
},
"devDependencies": {
  "@angular-devkit/build-angular": "~12.2.5",
  "@angular-eslint/builder": "12.4.1",
  "@angular-eslint/eslint-plugin": "12.4.1",
  "@angular-eslint/eslint-plugin-template": "12.4.1",
  "@angular-eslint/schematics": "12.4.1",
  "@angular-eslint/template-parser": "12.4.1",
  "@angular/cli": "~12.2.5",
  "@angular/compiler-cli": "~12.2.5",
  "@angular/language-service": "~12.2.5",
  "@nguniversal/builders": "12.1.0",
  "@types/core-js": "^2.5.5",
  "@types/express": "^4.17.13",
  "@types/jasmine": "~2.8.8",
  "@types/jasminewd2": "~2.0.3",
  "@types/lodash": "^4.14.172",
  "@types/node": "^16.9.0",
  "@types/sanitize-html": "^2.3.2",
  "@types/stripe-checkout": "^1.0.4",
  "@types/stripe-v3": "^3.1.25",
  "@typescript-eslint/eslint-plugin": "4.28.2",
  "@typescript-eslint/parser": "4.28.2",
  "codelyzer": "^6.0.2",
  "eslint": "^7.26.0",
  "jasmine-core": "~2.99.1",
  "jasmine-spec-reporter": "~4.2.1",
  "karma": "^5.1.1",
  "karma-chrome-launcher": "~2.2.0",
  "karma-coverage-istanbul-reporter": "~2.0.1",
  "karma-firefox-launcher": "^2.1.0",
  "karma-jasmine": "~1.1.2",
  "karma-jasmine-html-reporter": "^0.2.2",
  "karma-junit-reporter": "^1.2.0",
  "karma-spec-reporter": "0.0.32",
  "npm-run-all": "^4.1.5",
  "protractor": "^7.0.0",
  "rimraf": "^3.0.2",
  "ts-node": "^10.2.1",
  "tslint": "^6.1.3",
  "typescript": "~4.3.5"
}

angular.json中的build配置如下:

"build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
    "outputPath": "dist/frontend/browser",
    "index": "src/index.html",
    "main": "src/main.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "src/tsconfig.app.json",
    "assets": ["src/assets", "src/.well-known"],
    "allowedCommonJsDependencies": ["lodash", "@bugsnag/js", "ngx-barcode", "url-parse", "sanitize-html"],
    "styles": ["node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.less"],
    "scripts": [
      "./node_modules/jquery/dist/jquery.slim.min.js",
      "./node_modules/popper.js/dist/umd/popper.min.js"
    ]
  },
  "configurations": {
    "production": {
      "fileReplacements": [
        {
          "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.prod.ts"
        }
      ],
      "outputHashing": "all",
      "budgets": [
        {
          "type": "initial",
          "maximumWarning": "2mb",
          "maximumError": "5mb"
        },
        {
          "type": "anyComponentStyle",
          "maximumWarning": "6kb"
        }
      ]
    },
    "development": {
      "buildOptimizer": false,
      "optimization": false,
      "vendorChunk": true,
      "extractLicenses": false,
      "sourceMap": true,
      "namedChunks": true
    }
  },
  "defaultConfiguration": "production"
}

内容的提问来源于stack exchange,提问作者Charklewis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:39:00