web-dev-qa-db-fra.com

Qu'est-ce que le compilateur angular "compile")?

On me l'a demandé aujourd'hui et je n'ai pas été en mesure de donner une réponse appropriée.

TypeScript transpile en JS. Il y a ensuite le tremblement de l’arbre, "moins" (facultatif) et quoi d’autre dans le processus de déploiement. Mais rien de tel (autant que je sache) n'a rien à voir avec la "compilation". Tout est groupé et fortement optimisé, mais ce n’est pas réellement compilé, non?

Il existe même un compilateur en avance, qui fait vraiment un travail remarquable. Qu'est-ce qui me manque?

Javascript lui-même est toujours interprété, non?

81
codepleb

Vous supposez que compiler signifie prendre le code source et générer du code machine, des codes de bas niveau, etc. Mais compiler signifie simplement prendre un code source et le transformer en un autre. Il semble donc raisonnable de dire que prendre TypeScript et produire du JavaScript est une forme de compilation. Ce n'est pas différent de ce que (par exemple) c # fait quand il est compilé en langage IL.

Cela dit, je dirais un meilleur mot pour ceci est Transpiling. Je suggérerais que le compilateur TypeScript est mieux décrit comme un transpiler.

La différence est subtile et un transpiler peut être considéré comme un type de compilateur; mais un langage (pur) compilé transforme (généralement) un langage de haut niveau en un langage de niveau (inférieur) (plus proche du code machine), comme dans l'exemple C #. Un transpiler transforme un langage de haut niveau en un langage de niveau similaire (d'abstraction) (également de haut niveau).*

Le résultat du code compilé est généralement pas un langage que vous écririez vous-même. Le résultat d'un transpiler est un autre langage de haut niveau. En théorie, vous pourriez écrire IL (à titre d'exemple), mais il est vraiment conçu pour être produit par un compilateur et il n'existe aucun outil ou support pour le faire. Vous produisez IL en compilant C #/vb.net uniquement. Alors que Javascript est un langage de programmation utilisable (et utilisé) à part entière.

* Beaucoup de mises en garde comme les définitions de ces mots et leur utilisation sont assez vagues

88
Liam

Vous semblez poser trois questions en une:

  • Quelle est la différence entre un compilateur et un transpiler?
  • Est-ce que Angular et TypeScript implémentent des compilateurs ou des transpilers?
  • Existe-t-il un compilateur séparé Angular? Qu'est-ce qu'il compile?

Quelle est la différence entre un compilateur et un transpiler?

@ JörgWMittag a fourni une très bonne réponse à cette question.

Est-ce que Angular et TypeScript implémentent des compilateurs ou des transpilers?

TS et Angular implémentent des compilateurs réels . Ils suivent les mêmes étapes d'analyse lexicale, d'analyse syntaxique, d'analyse sémantique et de génération de code que C/C++ les compilateurs qui produisent le code Assembly (sauf probablement pour l'optimisation). Vous pouvez voir que la classe/dossier est nommé "compilateur" dans Angular et TS .

Le compilateur angular n'est pas vraiment lié au compilateur TypeScript. Ce sont des compilateurs très différents.

Existe-t-il un compilateur séparé Angular? Qu'est-ce qu'il compile?

Angular a deux compilateurs:

  • Voir le compilateur
  • Module compilateur

Le travail du compilateur de vues consiste à transformer le modèle que vous spécifiez pour le modèle de composant en représentation interne d’un composant qui est une fabrique de vues utilisé pour instancier une instance de vue .

Outre la transformation du modèle, le compilateur de vues compile également diverses informations de métadonnées sous la forme de décorateurs tels que @HostBinding, @ViewChild etc.

Supposons que vous définissiez un composant et son modèle comme ceci:

@Component({
  selector: 'a-comp',
  template: '<span>A Component</span>'
})
class AComponent {}

En utilisant ces données, le compilateur génère la fabrique de composants légèrement simplifiée suivante:

function View_AComponent {
  return jit_viewDef1(0,[
      elementDef2(0,null,null,1,'span',...),
      jit_textDef3(null,['My name is ',...])
    ]

Il décrit la structure d'une vue de composant et est utilisé lors de l'instanciation du composant. Le premier noeud est la définition de l'élément et le second est la définition du texte. Vous pouvez voir que chaque nœud obtient les informations dont il a besoin lorsqu'il est instancié via la liste de paramètres. C’est un travail de compilateur de résoudre toutes les dépendances requises et de les fournir au moment de l’exécution.

Je recommande fortement de lire ces articles:

Voir aussi la réponse à Quelle est la différence entre Angular AOT et le compilateur JIT.

Le travail du compilateur de modules consiste à créer une fabrique de modules contenant essentiellement les définitions fusionnées des fournisseurs.

Pour plus d'informations, lisez:

66

TypeScript transpire vers JS. Il y a ensuite le tremblement de l’arbre, "moins" (facultatif) et quoi d’autre dans le processus de déploiement. Mais rien de tel (autant que je sache) n'a rien à voir avec "compiler" Tout est groupé et fortement optimisé, mais ce n’est pas réellement compilé, non?

Compilation signifie transformer un programme écrit dans un langage A en un programme sémantiquement équivalent. écrit en langage B tel qu'évaluer le programme compilé selon les règles du langage (~ # ~] b [~ # ~] = (par exemple en l'interprétant avec un interprète pour B ) donne le même résultat et a les mêmes effets secondaires que l'évaluation du programme original selon les règles de langue A (par exemple en l'interprétant avec un interprète pour A ).

Compiler signifie simplement traduire un programme d'une langue A en langue B . C'est tout ce que cela signifie. (Notez également qu'il est parfaitement possible que A et B soit le même la langue.)

Dans certains cas, nous avons des noms plus spécialisés pour certains types de compilateurs, selon ce que A et B et que fait le compilateur:

  • if A est perçu comme étant le langage d'assemblage et B est perçu comme un langage machine , on appelle ça un assembleur ,
  • if A est perçu comme un langage machine et B est perçu comme un langage d'assemblage , on appelle cela un désassembleur ,
  • si A est perçu comme étant de niveau inférieur à B , alors nous l'appelons un décompilateur ,
  • si A et B sont la même langue, et le programme résultant est dans certaines plus rapide ou plus léger, on l’appelle un optimiseur ,
  • si A et B sont les mêmes langues et le programme résultant est plus petit, alors nous appelons cela un minificateur ,
  • if A et B sont les mêmes langues et le programme résultant est moins lisible. , nous appelons cela un obfuscateur ,
  • si A et B sont perçus comme se trouvant approximativement au même niveau d'abstraction, on appelle cela un transpiler , et
  • si A et B sont perçus comme étant à peu près au même niveau d'abstraction et le programme résultant préserve la mise en forme, les commentaires et l’intention du programmeur, de sorte qu’il est possible de conserver le programme résultant de la même manière que le programme original; on appelle cela un outil de réingénierie .

Notez également que les sources plus anciennes peuvent utiliser les termes "traduction" et "traducteur" au lieu de "compilation" et "compilateur". Par exemple, C parle d '"unités de traduction".

Vous pouvez également tomber sur le terme "processeur de langage". Cela peut signifier soit un compilateur, un interprète, soit des compilateurs et des interprètes, en fonction de la définition.

Javascript lui-même est toujours interprété, non?

JavaScript est un langage. Les langues sont un ensemble de règles logiques et de restrictions. Les langues ne sont pas interprétées ou compilées. Les langues juste sont .

La compilation et l'interprétation sont les traits d'un compilateur ou d'un interprète (duh!). Chaque langage peut être implémenté avec un compilateur et chaque langage peut être implémenté avec un interprète. Beaucoup de langues ont à la fois des compilateurs et des interprètes. De nombreux moteurs d'exécution hautes performances modernes ont à la fois au moins un compilateur et au moins un interprète.

Ces deux termes appartiennent à différentes couches d'abstraction. Si l'anglais était une langue dactylographiée, "langage interprété" serait une erreur de type.

Notez également que certaines langues n’ont ni interprète ni compilateur. Il y a des langues qui n'ont aucune implémentation. Pourtant, ce sont des langues et vous pouvez y écrire des programmes. Vous ne pouvez tout simplement pas les exécuter.

Notez également que tout est interprété à à un moment donné : si vous voulez exécuter quelque chose, vous devez l'interprète. La compilation ne fait que traduire le code d'une langue à une autre. Ça ne marche pas. Interprétation l'exécute. (Parfois, lorsqu'un interpréteur est implémenté dans le matériel, nous l'appelons un "CPU", mais c'est toujours un interprète.)

Exemple: chaque implémentation JavaScript principale existante actuellement existante a un compilateur.

La V8 a commencé comme un pur compilateur: elle compilait JavaScript directement dans du code machine natif modérément optimisé. Plus tard, un deuxième compilateur a été ajouté. À présent, il existe deux compilateurs: un compilateur léger qui produit un code modérément optimisé, mais le compilateur lui-même est très rapide et utilise peu de RAM. Ce compilateur injecte également du code de profilage dans le code compilé. Le deuxième compilateur est un compilateur plus lourd, plus lent et plus coûteux, qui produit cependant un code beaucoup plus étroit et beaucoup plus rapide. Il utilise également les résultats du code de profilage injecté par le premier compilateur pour prendre des décisions d'optimisation dynamiques. En outre, la décision de recompiler le code à l'aide du deuxième compilateur est prise en fonction de ces informations de profilage. Notez qu’à aucun moment un interprète n’est impliqué. La V8 n'interprète jamais, elle compile toujours. Il ne contient même pas d'interprète. (En fait, je crois que de nos jours, je décris les deux premières itérations.)

SpiderMonkey compile le code JavaScript dans le bytecode SpiderMonkey, qu’il interprète ensuite. L'interpréteur profile également le code, puis le code qui est exécuté le plus souvent est compilé par un compilateur en code machine natif. Ainsi, SpiderMonkey contient deux compilateurs : un de JavaScript en bytecode SpiderMonkey et un autre de bytecode SpiderMonkey en code machine natif.

Presque tous les moteurs d'exécution de JavaScript (à l'exception de V8) suivent ce modèle de compilateur AOT qui compile JavaScript en bytecode, ainsi qu'un moteur en mode mixte qui bascule entre l'interprétation et la compilation de ce bytecode.

Vous avez écrit dans un commentaire:

Je pensais vraiment que le code machine est quelque part impliqué.

Que veut dire "code machine"?

Quel est le langage machine d'un homme, quel est le langage intermédiaire d'un autre homme et vice versa? Par exemple, il existe des processeurs pouvant exécuter nativement le bytecode JVM. Sur un tel CPU, le bytecode JVM correspond au code natif de la machine. Et il existe des interpréteurs pour le code machine x86, lorsque vous exécutez ce code machine x86 est interprété par bytecode.

Il existe un interpréteur x86 appelé JPC écrit en Java. Si j'exécute du code machine x86 sur un JPC s'exécutant sur un processeur JVM natif… quel est le bytecode et quel est le code natif? Si je compile le code machine x86 en JavaScript (oui, il existe des outils permettant de le faire) et l’exécute dans un navigateur de mon téléphone (qui a ARM CPU), qui est le bytecode et Que se passe-t-il si le programme que je compile est un émulateur SPARC et que je l’utilise pour exécuter du code SPARC?)?

Notez que chaque langue induit une machine abstraite et constitue un langage machine pour cette machine. Ainsi, chaque langue (y compris les langues de très haut niveau) est un code machine natif. En outre, vous pouvez écrire un interprète pour chaque langue. Ainsi, chaque langue (y compris le code machine x86) n’est pas native.

49
Jörg W Mittag

Obtenir le code que vous avez écrit pour être exécuté sur un navigateur implique deux choses:

1) Transpiler le TypeScript en JavaScript . C'est un peu un problème résolu. Je pense qu'ils utilisent juste webpack.

2) Compilation des angular abstractions en JavaScript . Je veux dire des éléments tels que des composants, des tuyaux, des directives, des modèles, etc. C’est ce sur quoi l’équipe angular travaille.

Si vous êtes vraiment intéressé par ce second bit, le compilateur angular, l'auteur du compilateur, Tobias Bosch, explique le Angular Compiler à AngularConnect 2016 .

Je pense qu'il y a un peu de confusion entre transpiler et compiler. Cela n'a pas d'importance et c'est une question de goût personnel, ce sont deux transformations entre des représentations de code. Mais le définition que j'utilise personnellement est que la transpilation se situe entre deux langages différents à un niveau d'abstraction similaire (par exemple, TypeScript à javascript) , alors que la compilation nécessite un abaissement du niveau d'abstraction. Je pense que des modèles, des composants, des tuyaux, des directives, etc., au javascript, est une étape dans l’abstraction, et c’est pourquoi on l’appelle compilateur.

16
Nathan Cooper