webentwicklung-frage-antwort-db.com.de

Was "kompiliert" der angular - Compiler?

Das wurde ich heute gefragt und konnte keine richtige Antwort geben.

TypeScript wird in JS transpiliert. Dann gibt es Baumrütteln, "weniger" (optional) und was noch in dem Prozess der Bereitstellung. Aber nichts davon (afaik) hat etwas mit "Kompilieren" zu tun. Alles wird gebündelt und stark optimiert, aber es wird nicht kompiliert, oder?

Es gibt sogar einen Voraus-Compiler, der wirklich bemerkenswerte Arbeit leistet. Was vermisse ich?

Javascript selbst ist immer noch interpretiert, oder?

81
codepleb

Sie nehmen an, Kompilieren bedeutet, den Quellcode zu nehmen und Maschinencode, Low-Level-Codes usw. zu produzieren. Aber Kompilieren bedeutet eigentlich nur, einen Quellcode zu nehmen und ihn in einen anderen umzuwandeln. Es scheint also vernünftig zu sagen, dass die Verwendung von TypeScript und die Erstellung von JavaScript eine Form der Kompilierung ist . Es ist nicht unähnlich zu dem, was (zum Beispiel) c # macht, wenn es in IL-Sprache kompiliert wird.

Das heißt, ich würde sagen, ein besseres Wort dafür ist Transpiling. Ich würde vorschlagen, dass der TypeScript-Compiler besser als Transpiler beschrieben wird.

Der Unterschied ist subtil und ein Transpiler kann als eine Art Compiler betrachtet werden. Bei einer (reinen) kompilierten Sprache wird jedoch (normalerweise) eine Sprache auf hoher Ebene in eine Sprache auf niedriger (er) Ebene (näher am Maschinencode) umgewandelt, wie im C # -Beispiel. Ein Transpiler verwandelt eine Hochsprache in eine ähnliche (Abstraktions-) Sprache (auch Hochsprache).*

Das Ergebnis des kompilierten Codes ist normalerweise keine Sprache, die Sie selbst schreiben würden. Das Ergebnis eines Transpilers ist eine weitere Hochsprache. Theoretisch könnten Sie IL schreiben (als Beispiel), aber es ist wirklich so konzipiert, dass es von einem Compiler erstellt wird, und es gibt keine Tools oder Unterstützung dafür. Sie erstellen IL nur durch Kompilieren von C #/vb.net. Während Javascript eine benutzbare (und benutzte) Programmiersprache für sich ist.

* Viele Vorbehalte, wie die Definitionen dieser Wörter und ihre Verwendung sind ziemlich vage

88
Liam

Sie scheinen drei Fragen in einer zu stellen:

  • Was ist der Unterschied zwischen einem Compiler und einem Transpiler?
  • Implementieren Angular und TypeScript Compiler oder Transpiler?
  • Gibt es einen separaten Angular Compiler? Was kompiliert er?

Was ist der Unterschied zwischen einem Compiler und einem Transpiler?

@ JörgWMittag lieferte eine sehr gute Antwort auf diese Frage.

Implementieren Angular und TypeScript Compiler oder Transpiler?

Sowohl TS als auch Angular implementieren real Compiler. Sie durchlaufen dieselben Phasen der lexikalischen Analyse, Analyse, semantischen Analyse und Codegenerierung wie C/C++ - Compiler, die Assembly-Code erzeugen (mit Ausnahme wahrscheinlich zur Optimierung). Sie können sehen, dass die Klasse/der Ordner sowohl in Angular als auch in TS als "Compiler" bezeichnet wird.

Der Compiler angular ist nicht wirklich mit dem TypeScript-Compiler verwandt. Dies sind sehr unterschiedliche Compiler.

Gibt es einen separaten Angular Compiler? Was kompiliert er?

Angular hat zwei Compiler:

  • Compiler anzeigen
  • Modul-Compiler

Die Aufgabe des View-Compilers besteht darin, die Vorlage, die Sie für die Komponentenvorlage angegeben haben, in die interne Darstellung einer Komponente umzuwandeln, die dann eine View-Factory ist Dient zum Instanziieren einer Ansichtsinstanz .

Der View Compiler transformiert nicht nur die Vorlage, sondern erstellt auch verschiedene Metadateninformationen in Form von Dekoratoren wie @HostBinding, @ViewChild etc.

Angenommen, Sie definieren eine Komponente und ihre Vorlage wie folgt:

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

Aus diesen Daten generiert der Compiler die folgende leicht vereinfachte Komponentenfactory:

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

Es beschreibt die Struktur einer Komponentensicht und wird beim Instanziieren der Komponente verwendet. Der erste Knoten ist die Elementdefinition und der zweite die Textdefinition. Sie können sehen, dass jeder Knoten die Informationen erhält, die er benötigt, wenn er über die Parameterliste instanziiert wird. Es ist Aufgabe eines Compilers, alle erforderlichen Abhängigkeiten aufzulösen und zur Laufzeit bereitzustellen.

Ich empfehle dringend, diese Artikel zu lesen:

Siehe auch die Antwort auf Was ist der Unterschied zwischen Angular AOT- und JIT-Compiler.

Die Aufgabe des Modul-Compilers besteht darin, eine Modul-Factory zu erstellen, die im Wesentlichen zusammengeführte Definitionen der Anbieter enthält.

Weitere Informationen finden Sie unter:

TypeScript wird in JS übertragen. Dann gibt es Baumrütteln, "weniger" (optional) und was noch in dem Prozess der Bereitstellung. Aber nichts davon (afaik) hat etwas mit "Kompilieren" zu tun. Alles wird gebündelt und stark optimiert, aber es wird nicht kompiliert, oder?

Compilation bedeutet, ein in einer Sprache geschriebenes Programm A in ein semantisch äquivalentes Programm umzuwandeln, das in einer Sprache geschrieben ist B so, dass das kompilierte Programm nach den Regeln der Sprache ausgewertet wird B (zum Beispiel mit einem Dolmetscher interpretiert) für B ) ergibt das gleiche Ergebnis und hat die gleichen Nebenwirkungen wie die Bewertung des Originalprogramms nach den Regeln der Sprache A (zum Beispiel mit einem Interpreter interpretieren für A ).

Kompilieren bedeutet einfach, ein Programm von language A in language B zu übersetzen. Das ist alles was es bedeutet. (Beachten Sie auch, dass A und B durchaus gleich sein können Sprache.)

In einigen Fällen haben wir spezialisiertere Namen für bestimmte Arten von Compilern, je nachdem, was A und B are und was der Compiler macht:

  • if A wird als Assemblersprache und B als Maschinensprache wahrgenommen , dann nennen wir es Assembler,
  • if A wird als Maschinensprache und B als Assemblersprache wahrgenommen , dann nennen wir es disassembler,
  • wenn A als niedriger wahrgenommen wird als B , dann nennen wir es a Decompiler,
  • if A und B sind die gleiche Sprache und das resultierende Programm ist in einigen viel schneller oder leichter, dann nennen wir es Optimierer,
  • wenn A und B die gleichen Sprachen sind und das resultierende Programm kleiner ist, dann nennen wir es minifier,
  • wenn A und B die gleichen Sprachen sind und das resultierende Programm weniger lesbar ist , dann nennen wir es Obfuscator,
  • wenn A und B in etwa auf der gleichen Abstraktionsebene wahrgenommen werden, dann nennen wir es transpiler und
  • wenn A und B in etwa auf der gleichen Abstraktionsstufe wahrgenommen werden und Das resultierende Programm behält Formatierungen, Kommentare und Programmierer-Absichten bei, so dass es möglich ist, das resultierende Programm auf die gleiche Weise wie das ursprüngliche Programm zu pflegen. Dann nennen wir es ein Re-Engineering-Tool.

Beachten Sie auch, dass ältere Quellen möglicherweise die Begriffe "Übersetzung" und "Übersetzer" anstelle von "Kompilierung" und "Compiler" verwenden. Zum Beispiel spricht C von "Übersetzungseinheiten".

Sie können auch über den Begriff "Sprachprozessor" stolpern. Dies kann je nach Definition entweder einen Compiler, einen Interpreter oder sowohl Compiler als auch Interpreter bedeuten.

Javascript selbst wird immer noch interpretiert, oder?

JavaScript ist eine Sprache. Sprachen sind eine Reihe von logischen Regeln und Einschränkungen. Sprachen werden nicht interpretiert oder kompiliert. Sprachen nur sind.

Zusammenstellung und Interpretation sind Eigenschaften eines Compilers oder Interpreten (duh!). Jede Sprache kann mit einem Compiler implementiert werden und jede Sprache kann mit einem Interpreter implementiert werden. Viele Sprachen haben sowohl Übersetzer als auch Dolmetscher. Viele moderne High-Performance-Execution-Engines verfügen sowohl über mindestens einen Compiler als auch über mindestens einen Interpreter.

Diese beiden Begriffe gehören zu verschiedenen Abstraktionsebenen. Wenn Englisch eine getippte Sprache wäre, wäre "interpretierte Sprache" ein Tippfehler.

Beachten Sie auch, dass einige Sprachen weder einen Interpreter noch einen Compiler haben. Es gibt Sprachen, die überhaupt nicht implementiert sind. Trotzdem sind sie Sprachen, und Sie können Programme in ihnen schreiben. Sie können sie einfach nicht ausführen.

Beachten Sie auch, dass alles zu irgendwann interpretiert wird: Wenn Sie etwas ausführen möchten, müssen Sie muss interpretieren. Die Kompilierung übersetzt nur Code von einer Sprache in eine andere. Es läuft nicht. Interpretation führt es aus. (Wenn ein Interpreter in Hardware implementiert ist, wird er manchmal als "CPU" bezeichnet, ist aber immer noch ein Interpreter.)

Ein typisches Beispiel: Jede derzeit vorhandene Mainstream-JavaScript-Implementierung verfügt über einen Compiler.

V8 begann als reiner Compiler: Es kompilierte JavaScript direkt zu mäßig optimiertem nativem Maschinencode. Später wurde ein zweiter Compiler hinzugefügt. Nun gibt es zwei Compiler: einen kompakten Compiler, der mäßig optimierten Code erzeugt, der selbst jedoch sehr schnell ist und wenig RAM verbraucht. Dieser Compiler fügt außerdem Profiling-Code in den kompilierten Code ein. Der zweite Compiler ist ein schwererer, langsamerer und teurerer Compiler, der jedoch viel dichteren, viel schnelleren Code erzeugt. Außerdem werden die Ergebnisse des vom ersten Compiler eingegebenen Profiling-Codes verwendet, um dynamische Optimierungsentscheidungen zu treffen. Die Entscheidung, welcher Code unter Verwendung des zweiten Compilers erneut kompiliert werden soll, wird auf der Grundlage dieser Profilinformationen getroffen. Beachten Sie, dass zu keinem Zeitpunkt ein Dolmetscher beteiligt ist. V8 interpretiert nie, es kompiliert immer. Es enthält nicht einmal einen Dolmetscher. (Eigentlich glaube ich, dass es heutzutage so ist, ich beschreibe die ersten beiden Iterationen.)

SpiderMonkey kompiliert JavaScript in SpiderMonkey-Bytecode, den es dann interpretiert. Der Interpreter erstellt auch ein Profil für den Code, und der Code, der am häufigsten ausgeführt wird, wird von einem Compiler zu systemeigenem Maschinencode kompiliert. SpiderMonkey enthält also zwei Compiler: einen von JavaScript zu SpiderMonkey-Bytecode und einen anderen von SpiderMonkey-Bytecode zu nativem Maschinencode.

Nahezu alle JavaScript-Ausführungsmodule (mit Ausnahme von V8) folgen diesem Modell eines AOT-Compilers, der JavaScript zu Bytecode kompiliert, und einer Mixed-Mode-Engine, die zwischen dem Interpretieren und Kompilieren dieses Bytecodes wechselt.

Sie haben in einem Kommentar geschrieben:

Ich dachte wirklich, dass Maschinencode irgendwo beteiligt ist.

Was bedeutet "Maschinencode" überhaupt?

Was ist die Maschinensprache eines Mannes ist die Zwischensprache eines anderen Mannes und umgekehrt? Beispielsweise gibt es CPUs, die JVM-Bytecode nativ ausführen können. Auf einer solchen CPU ist JVM-Bytecode is nativer Maschinencode. Und es gibt Interpreter für x86-Maschinencode, wenn Sie diesen x86-Maschinencode ausführen ist interpretierten Bytecode.

Es gibt einen in Java geschriebenen x86-Interpreter namens JPC. Wenn ich x86-Maschinencode in JPC auf einer nativen JVM-CPU ausführe, welcher ist der Bytecode und welcher der native Code? Wenn ich x86-Maschinencode in JavaScript kompiliere (ja, es gibt Tools, die das können), starte ich ihn in einem Browser auf meinem Telefon (der eine ARM CPU) hat, die der Bytecode ist, und Was ist, wenn das Programm, das ich kompiliere, ein SPARC Emulator ist und ich es verwende, um SPARC Code auszuführen?

Beachten Sie, dass every language eine abstrakte Maschine induziert und Maschinensprache für diese Maschine ist. Daher ist jede Sprache (einschließlich der Hauptsprachen) ein systemeigener Maschinencode. Sie können auch einen Dolmetscher für jede Sprache schreiben. Daher ist jede Sprache (einschließlich x86-Maschinencode) nicht muttersprachlich.

49
Jörg W Mittag

Damit der von Ihnen geschriebene Code in einem Browser ausgeführt werden kann, sind zwei Dinge erforderlich:

1) Transpilieren Sie das TypeScript in JavaScript . Dies ist eine Art gelöstes Problem. Ich denke, dass sie nur Webpack verwenden.

2) Kompilieren der angular Abstraktionen in JavaScript Ich meine Dinge wie Komponenten, Pipes, Direktiven, Vorlagen usw. Daran arbeitet das angular Kernteam.

Falls Sie sich wirklich für dieses zweite Bit interessieren, den angular compiler, watch compiler author Tobias Bosch erklärt den Angular Compiler bei AngularConnect 2016 .

Ich denke, dass es hier ein bisschen Verwirrung zwischen Transpilieren und Kompilieren gibt. Es spielt sozusagen keine Rolle und ist eine Frage des persönlichen Geschmacks, sie sind beide nur Transformationen zwischen Repräsentationen von Code. Aber das Definition , das ich persönlich benutze, ist, dass die Transpilation zwischen zwei verschiedenen Sprachen auf einer ähnlichen Abstraktionsebene erfolgt (z. B. TypeScript zu Javascript). Während Kompilierung einen Schritt in der Abstraktionsebene erfordert. Ich denke, von Vorlagen, Komponenten, Pipes, Direktiven usw. bis hin zu einfachem Javascript ist ein Schritt in der Abstraktionsleiter, und deshalb wird es Compiler genannt.

16
Nathan Cooper