Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a Compilation Context in Angular?

In the Angular documentation it says that Modules share a compilation context.

NgModules provide a compilation context for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.

source

I only found one explanation here. But I don't quite fully understand it or the importance of it. Could someone elaborate exactly on what a "Compilation Context" means and what is the importance that Modules share the same context?

like image 515
Luke Xu Avatar asked Jun 20 '18 04:06

Luke Xu


1 Answers

Angular documentation says that

The components that belong to an NgModule share a compilation context.

Have you ever heard the errors like

WARNING: Template parse errors: 'A' is not a known element:

  1. If 'b-comp' is an Angular component, then verify that it is part of this module.

  2. If 'b-comp' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.

or

Can't bind to 'ngModel' since it isn't a known property of 'input'


Compilation Context

The explanation from the link, you've found, correctly describes notion of compilation context.

It's group of something(files, components) which will be compiled. It implies that the context contains everything a compiler needs to compile without any errors.

Imagine you compile typescript and you control context by using tsconfig.json file where define files, include or exclude options. This way typescript compiler will use only files your provides to find relations between your ts code.

Angular Compiler

Now let's come back to Angular compiler.

Angular compiler basically compiles component's templates. To compile template Angular should know all components/directives that are involved in this template.

Let's say we have the following straightforward component:

@Component({
  selector: 'a-comp`,
  template: `
    <h2>Hello, I'm a-comp</h2>
    <div [scroll]="options">
      <b-comp></b-comp>
    </div>
  `
})
export class ComponentA {}

and this component is defined in some Angular module like:

@NgModule({
  declarations: [
    ComponentA
  ]
})
export class AModule {}

In order to compile ComponentA angular goes through the following phases:

1) Find NgModule to which it belongs.

ComponentA was declared in AModule so this module becomes its compilation context.

2) Find all other directives which are in scope of this module.

Angular is searching for all transitive modules of this NgModule. (Angular 2 Use component from another module)

3) Run compilation by passing all involved directives to compiler

compileComponent(outputCtx, compMeta, ngModule, ngModule.transitiveModule.directives 
                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Our AModule doesn't import any other modules and doesn't define any other directives. This means that Angular won't be able to compile template of ComponentA(if you didn't use CUSTOM_ELEMENTS_SCHEMA of course):

<div [scroll]="options">
  <b-comp></b-comp>
</div>

because Angular compiler will look for directive with scroll @Input and for b-comp but our the scope AModule doesn't contain such directives.

In other words NgModule didn't provide the correct compilation context for building a component. NgModule is a kind of configuration for Angular compiler like tsconfig.json for typescript compiler.

Again, the components declared in NgModule and components, imported from other modules that are exported them, share the same compilation context (More on this here Angular 2 Use component from another module)

like image 132
yurzui Avatar answered Oct 05 '22 08:10

yurzui