In this post, we are going to look at Entry Components in Angular, what they are and why they even exist. In the simplest terms possible, an entry component in Angular is any component that is loaded by its class, not selector.

@Component({
  selector: 'app-some-component', // <== component select tags
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppSomeComponent {
  // <== Component Class
}

Normally, in angular, when loading a component, you use the component selector, inside the template. In the case of the above component, the selector is app-some-component and the class is AppSomeComponent. So, normally the above component would be loaded like this:

<app-some-component></app-some-component>

This sort of components are declared components and are added as an array inside the declarations section of the app or feature module. But from time to time, you may need to reference to a component by its class. A good example of this is when adding a component to your app router. You refer to the component by the class and not the selector.

const routes: Routes = [
  {
    path: '',
    component: ComponentClassName,
    children: []
  }
]

Entry components must be registered inside the app or feature module, under entryComponents section. But this does not apply to all components, Angular automatically registers some entry components for you. For instance, any component found in your routes will be registered by Angular CLI during compilation. Therefore, most developer deal with entry components without even realizing so.

Why do I need to register Entry Components

Normally, all components are declared inside the app or feature module under declarations. This applies to all components inside your project, whether they have been used or not. This is even before you consider components declared by third party libraries that you might not need in your project.

If all these unused components were to end up in the final app bundle, they would considerably increase its size. And remember, our goal is to have as small final bundle as possible. To work around this, Angular CLI tree shakes your app during build time. It removes all components that have not been referenced (declared) in your template.

Now, remember that an entry component is used or referenced by its class and not inside some other components template (at least most of the time). Without a list of entry components, Angular CLI would fail to include these components in the final bundle, hence breaking your application. Therefore, for most entry components, you need to register them under entryComponents array, in your app or feature module.

...
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    ...
  ],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [
    SomeEntryComponent
  ]
})
export class AppModule { }

NB: Commonly used entry components like routing and bootstrap components are automatically registered for us. It would be very painful if you had to keep track and (un)register them manually. If you forget to add an entry component, angular will show the an error message similar or close to this.

So, the next time you encounter such an error, just add it to the list of entry components to your module.

Conclusion

As you have seen in this post, entry components are overall a good thing. They make it possible to tree shake your app and reduce the final bundle size, without needing any optimization from the developer. Most developers rarely encounter them, because third party library register their own entry components, although not in all situations. For instance, dialog or modal libraries like Angular Material Dialog or ng-bootstrap modal, you are required to register referenced components as entry components. Hope this post helped you understand entry components much better. If you have a topic you would like to see me to cover, leave it in the comment section below.