Julius Dzidzevičius
Julius Dzidzevičius

Reputation: 11000

Can Angular have more than one bootstrap component?

Stupid question alert:

In our main app.module.ts file we set bootstrap parameter with value that defines our top-level component. So with this:

@NgModule({
  bootstrap: [AppComponent]
})

We tell that when our module is used, our top-level component is AppComponent. But why it is in array? Can there be more top-level components...?

Upvotes: 9

Views: 6530

Answers (2)

Max Koretskyi
Max Koretskyi

Reputation: 105547

Yes, Angular can have many top-level components. You can check it easily for yourself:

@Component({selector: 'a-comp', template: `A comp`})
export class AComp {}

@Component({selector: 'b-comp', template: `B comp`})
export class BComp {}


@NgModule({
  imports: [BrowserModule],
  declarations: [AComp, BComp],
  bootstrap: [AComp, BComp]
})
export class AppModule {
}

------------------

<body>
    <a-comp></a-comp>
    <b-comp></b-comp>
</body>

Under the hood mechanics

Angular will create two separate trees of views and attach both to the ApplicationRef here

PlatformRef_.prototype._moduleDoBootstrap = function (moduleRef) {
        var appRef = (moduleRef.injector.get(ApplicationRef));
        if (moduleRef._bootstrapComponents.length > 0) {
            moduleRef._bootstrapComponents.forEach(function (f) { return appRef.bootstrap(f); });
  --------------------------------

  // will be called two times
  ApplicationRef_.bootstrap = function (componentOrFactory, rootSelectorOrNode) {

  ...
  ApplicationRef.attachView(viewRef: ViewRef): void {
    const view = (viewRef as InternalViewRef);
    this._views.push(view);
    view.attachToAppRef(this);
  }

And then, when change detection will run applicationRef will go through these two views:

  ApplicationRef.tick(): void {
    ...
    try {
      this._views.forEach((view) => view.detectChanges());
      ...

Fascinating things

What's even more fascinating is that you can attach the <b-comp> to the application programatically without specifying the component BComponent in the module.boostrap: []:

export class AComponent {
  constructor(r: ComponentFactoryResolver, app: ApplicationRef) {
    const f = r.resolveComponentFactory(BComponent);
    app.bootstrap(f, 'b-comp');

---------------

@NgModule({
  imports: [BrowserModule],
  declarations: [AComponent, BComponent],
  entryComponents: [BComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

--------------

<body>
    <a-comp></a-comp>
    <b-comp></b-comp>
</body>

Upvotes: 11

Alejandro Lora
Alejandro Lora

Reputation: 7842

That's because you can bootstrap different modules to have different apps at the same time.

You can see this sample here:

Bootstrapping muliple components in Angular2

Which the important parts is:

@NgModule({
  imports: [],
  declarations: [App1, App2, App3],
  bootstrap: [App1, App2, App3]
})
export class BaseModule {}

<body>
   <app1>App1</app1>
  <app2>App1</app2>
  <app3>App1</app3>
</body>

Upvotes: 1

Related Questions