Webpack编译后ng2-bootstrap-modal无法创建对话框容器求助
I've run into similar headaches with libraries relying on Angular's private internal properties—they're not intended for public use and often get mangled or stripped out by production optimizers. Here are actionable fixes tailored to your issue:
1. Patch the Library to Avoid Private Property Dependencies (Quick Fix)
The root problem is that _rootComponents is an undocumented private Angular property. Webpack's minifier might obfuscate its name in production, or it might not exist at all depending on your Angular version. You can modify the createDialogHolder method to use a more reliable container source:
- Locate
dialog.service.jsin yournode_modules/ng2-bootstrap-modalfolder - Replace the faulty container-fetching logic:
// Original problematic code // if (!this.container) { // var componentRootViewContainer = this.applicationRef['_rootComponents'][0]; // this.container = componentRootViewContainer.hostView.rootNodes[0]; // } // Updated code: Use configured container or fallback to document.body if (!this.container) { this.container = this.options?.container || document.body; } - To keep this change permanent across
npm install, usepatch-packageto create a local patch for the library—this ensures your fix doesn't get overwritten.
2. Switch to a Maintained Modal Library (Long-Term Solution)
ng2-bootstrap-modal hasn't seen updates in years, making it incompatible with modern Angular and Webpack production pipelines. For a stable, supported alternative, migrate to one of these:
- Angular Material Dialog: Official, fully supported, and built for production-grade apps
- ng-bootstrap Modal: Tightly integrated with Bootstrap and actively maintained
Both libraries avoid relying on Angular's internal APIs, so you won't hit this kind of production-specific bug again.
3. Configure Webpack to Preserve the Private Property
If you absolutely need to stick with ng2-bootstrap-modal, you can tell Webpack's minifier to leave _rootComponents untouched. In your production Webpack config:
const TerserPlugin = require('terser-webpack-plugin'); module.exports = { optimization: { minimizer: [ new TerserPlugin({ terserOptions: { mangle: { reserved: ['_rootComponents'] // Prevent this property from being mangled } } }) ] } };
⚠️ Note: This is a fragile workaround—Angular could rename or remove _rootComponents in any update, breaking your code without warning.
4. Manually Inject a Container Reference
You can explicitly provide a container element to the DialogService instead of letting it fetch one internally:
- In your
app.component.html, add a dedicated container element:<div #modalContainer class="modal-container"></div> - In
app.component.ts, pass this element to the DialogService:import { Component, ViewChild, ElementRef, OnInit } from '@angular/core'; import { DialogService } from 'ng2-bootstrap-modal'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { @ViewChild('modalContainer', { static: true }) modalContainer!: ElementRef; constructor(private dialogService: DialogService) {} ngOnInit(): void { // Override the container in DialogService (this.dialogService as any).container = this.modalContainer.nativeElement; } }
This completely bypasses the broken _rootComponents lookup.
内容的提问来源于stack exchange,提问作者Ovidiu Rudi

