web-dev-qa-db-fra.com

Quelle est la différence entre Angular AOT et JIT compilateur

Je plonge dans angular 4 et j'essaie de comprendre la compilation. J'ai lu que AOT et JIT compilent tous les deux TypeScript en JavaScript, que ce soit côté serveur ou côté client. Si je suis-je en train de le compiler quand je le construis avec Webpack et grunt et de déployer ce javascript minimisé comment AOT et JIT entrent-ils dans l'image?

13
CW1

J'ai lu que AOT et JIT compilent tous deux TypeScript en JavaScript, que ce soit côté serveur ou côté client.

Non, ce n'est pas ce que font les compilateurs AOT et JIT. TypeScript est transposé en JavaScript à l'aide du compilateur TypeScript.

Compilateur angulaire

Il existe deux compilateurs qui effectuent le dur travail de compilation et de génération de code:

Le compilateur de vue compile les modèles de composants et génère des fabriques de vues . Il analyse les expressions et les éléments html à l'intérieur du modèle et passe par de nombreuses phases de compilation standard:

parse-tree (lexer) -> abstract-syntax-tree (parser) -> intermediate-code-tree -> output

Le compilateur de fournisseurs compile les fournisseurs de modules et génère des usines de modules .

JIT vs AOT

Ces deux compilateurs sont utilisés dans les compilations JIT et AOT. Les compilations JIT et AOT diffèrent dans la façon dont elles obtiennent les métadonnées associées au composant ou au module:

// the view compiler needs this data

@Component({
   providers: ...
   template: ...
})

// the provider compiler needs this data

@NgModule({
   providers: ...
});

Le compilateur JIT utilise le runtime pour obtenir les données. Le décorateur fonctionne @Component et @NgModule sont exécutés et ils attachent des métadonnées à la classe de composant ou de module qui est ensuite lue par Angular utilisant des capacités réfléchissantes (bibliothèque Reflect).

Le compilateur AOT utilise l'analyse de code statique fournie par le compilateur TypeScript pour extraire les métadonnées et ne repose pas sur l'évaluation de code. Par conséquent, il est un peu limité par rapport au compilateur JIT car il ne peut pas évaluer le code non explicite - par exemple, il nécessite l'exportation d'une fonction:

// this module scoped function

function declarations() {
  return [
    SomeComponent
  ]
}

// should be exported

export function declarations() {
  return [
    SomeComponent
  ];
}
@NgModule({
  declarations: declarations(),
})
export class SomeModule {}

Encore une fois, les compilateurs JIT et AOT sont principalement des wrappers pour extraire les métadonnées associées à un composant ou un module et ils utilisent tous deux la vue sous-jacente et le compilateur de fournisseur pour générer des usines.

Si je le compile quand je le construis avec Webpack et grunt et déploie ce javascript minimisé, comment AOT et JIT apparaissent-ils même dans l'image?

Angular fournit plugin webpack qui effectue la transpilation à partir de TypeScript pendant la construction. Ce plugin peut également AOT compiler votre projet afin que vous n'incluiez pas le compilateur JIT dans le bundle et n'effectuiez pas de compilation sur le client.

23

Tout d'abord angular s'éloigne de la compilation JIT. J'espère que nous le verrons dans [email protected]

Le compilateur angulaire prend toutes les métadonnées que vous écrivez en utilisant des décorateurs comme

@Component({
  selector: 'my-app',
  template: '<h1>Hello</h1>'m
  styles: [ ':Host { display: block }' ]
})

constructor(
  @Host() @Optional() private parent: Parent,
  @Attribute('name') name: string) {} 

@ViewChild('ref') ref;

@ContentChildren(MyDir) children: QueryList<MyDir>;  

@HostBinding('title') title;

@HostListener('click') onClick() { ... }

// and so on

et l'analise. Ensuite, il prend le modèle et les feuilles de style et les analyse. Le compilateur passe par de nombreuses étapes que je ne décrirai pas ici. Vous pouvez jeter un œil à la page suivante qui décrit le processus de compilation. Il y a aussi grand discours de Tobias Bosch. Enfin, le compilateur crée des ngfactories pour instancier notre application.

Je pense que les principales différences entre AOT dans JIT sont

  • quand et où angular exécute la compilation
  • comment le compilateur collecte les métadonnées
  • quel est le format de ngfactory que le compilateur produit

Compilateur JIT

s'exécute côté client dans notre navigateur à chaque chargement de page .

Il collecte des métadonnées à l'aide de ReflectionCapabilities API from @angular/core paquet. Nous avons les options suivantes pour travailler avec des métadonnées en mode JIT:

1) API directe

par exemple, nous pouvons déclarer notre composant comme

export class AppComponent {
  static annotations = [
    new Component({
      selector: 'my-app',
      templateUrl: `./app.component.html`,
      styles: [ ':Host { display: block }' ]
    })
  ];

  test: string;

  static propMetadata = {
      test: [new HostBinding('title')]
  };


  ngOnInit() {
    this.test = 'Some title'
  }
}

Un code similaire que nous pouvons écrire dans ES5. Le compilateur JIT lira les propriétés statiques annotations et propMetadata. Le compilateur AOT ne fonctionnera pas avec.

2) API tsickle

export class AppComponent {
  static decorators = [{
      type: Component,
      args: [{
        selector: 'my-app',
        templateUrl: `./app.component.html`,
        styles: [ ':Host { display: block }' ]
      },]
  }];

  test: string;

  static propDecorators = {
    'test': [{ type: HostBinding, args: ['title'] }]
  };

  ngOnInit() {
    this.test = 'Some title'
  }
}

Le code ci-dessus est généralement généré par une bibliothèque. Angular a également le même format. Cela ne fonctionnera pas non plus avec aot. Nous devons expédier metadata.json fichier avec notre bibliothèque pour la compilation AOT.

3) Obtenir des métadonnées créées en invoquant les décorateurs

@Component({
  selector: 'my-app',
  templateUrl: `./app.component.html`
})
export class AppComponent {
  @HostBinding('title') test = 'Some title';
}

Le compilateur TypeScript transforme le code précédent en

 var AppComponent = (function () {
    function AppComponent() {
        this.test = 'Some title';
    }
    return AppComponent;
}());
__decorate([
    HostBinding('title')
], AppComponent.prototype, "test", void 0);
AppComponent = __decorate([
    Component({
        selector: 'my-app',
        templateUrl: "./app.component.html"
    })
], AppComponent);

ce code est exécuté en mode JIT donc angular appelle le décorateur de composants

const TypeDecorator: TypeDecorator = <TypeDecorator>function TypeDecorator(cls: Type<any>) {
      // Use of Object.defineProperty is important since it creates non-enumerable property which
      // prevents the property is copied during subclassing.
      const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
          (cls as any)[ANNOTATIONS] :
          Object.defineProperty(cls, ANNOTATIONS, {value: []})[ANNOTATIONS];
      annotations.Push(annotationInstance);
      return cls;
};

Aujourd'hui, il n'utilise plus l'API Reflect . Le compilateur lit les données directement à partir de __annotations__ propriété

if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
  return (typeOrFunc as any)[ANNOTATIONS];
}

Le compilateur JIT produit des ngfactories javascript

Compilateur AOT

s'exécute côté serveur (nodejs) au moment de la construction en utilisant ngc.

Avec AOT, il n'y a pas d'étape de compilation à l'exécution. Lorsque nous exécutons notre application dans un navigateur, nous avons déjà précompilé ngfactories. Cela nous donne de meilleures performances au premier chargement et paresseux. Nous n'expédions pas non plus @angular/compiler code dans notre bundle de production. Mais notre offre peut se développer considérablement en raison de notre code ngfactories.

Le compilateur AOT utilise API TypeScript pour analyser le code TypeScript. Pour obtenir le compilateur de métadonnées passe par les API StaticSymbolResolver et MetadataCollector .

Il faut donc app.component.ts fichier et crée un modèle d'objet TypeScript. Ainsi, notre classe AppComponent sera présentée comme NodeObject avec le type 229 (ClassDeclaration)

enter image description here

comme nous pouvons le voir, cet objet a la propriété decorators

enter image description here

et un wrapper TypeScript spécial écrit par angular angulaire et appelé tsc-wrappertravaille dur pour extraire ces métadonnées.

Lorsque le compilateur rencontre d.ts file il essaie d'obtenir des métadonnées à partir de metadata.json:

if (DTS.test(filePath)) {
  var metadataPath = filePath.replace(DTS, '.metadata.json');
  if (this.context.fileExists(metadataPath)) {
    return this.readMetadata(metadataPath, filePath);
  }
  else {
    // If there is a .d.ts file but no metadata file we need to produce a
    // v3 metadata from the .d.ts file as v3 includes the exports we need
    // to resolve symbols.
    return [this.upgradeVersion1Metadata({ '__symbolic': 'module', 'version': 1, 'metadata': {} }, filePath)];
  }
}

Et enfin, le compilateur AOT utilise TypeScriptEmitter pour produire des ngfactories TypeScript (angulaire <4.4.0)

Voir également

18
yurzui

Une fois que le navigateur a chargé vos ensembles d'applications, le compilateur Angular (inclus dans vendor.bundle.js) effectue la compilation des modèles à partir de main.bundle.js. Cela s'appelle Just-in-Time compilation: ce terme signifie que la compilation a lieu au moment de l'arrivée des bundles sur le navigateur.

Les inconvénients de la compilation JIT sont:

  1. Il y a un intervalle de temps entre le chargement des faisceaux et le rendu de l'interface utilisateur. Ce temps est consacré à la compilation de JiT. Sur une petite application, cette fois est minime, mais dans les applications plus grandes, la compilation JiT peut prendre quelques secondes, donc l'utilisateur doit attendre plus longtemps pour ne voir que votre application.

  2. Le compilateur Angular doit être inclus dans le fichier vendor.bundle.js, ce qui augmente la taille de votre application.

L'utilisation de la compilation JiT dans la prod est déconseillée, et nous voulons que les modèles soient précompilés en JavaScript avant la création des bundles. C'est à cela que sert la compilation Ahead-of-Time (AoT).

Les avantages de la compilation AoT sont:

  1. Le navigateur peut rendre l'interface utilisateur dès que votre application est chargée. Il n'est pas nécessaire d'attendre la compilation du code.

  2. Le compilateur ngc n'est pas inclus dans vendor.bundle.js et la taille résultante de votre application peut être plus petite.

Si vous utilisez Webpack, pour faire AoT, vous devez appeler le compilateur ngc. Par exemple:

"build:aot": "ngc -p tsconfig.json && webpack --config webpack.config.js"
4
Yakov Fain