Was „kompiliert“ der Winkelcompiler?

87

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

Typoskript transpiliert nach JS. Dann gibt es Baumschütteln, "weniger" (optional) und was sonst noch im Prozess der Bereitstellung. Aber nichts dergleichen (afaik) hat etwas mit "Kompilieren" zu tun. Alles wird gebündelt und stark optimiert, aber es wird nicht wirklich kompiliert, oder?

Es gibt sogar einen "Ahead-of-Time" -Compiler, der wirklich spürbare Arbeit leistet. Was vermisse ich?

Javascript selbst wird immer noch interpretiert, oder?

Codepleb
quelle
6
Ich stimme dem "nicht wirklich kompilieren" zu. Im Wesentlichen geht es um die Definition der Zusammenstellung . Einige bevorzugen die Verwendung des Wortes Transpilation , um die Umwandlung von TypeScript in JavaScript zu markieren. Aber ja, im Wesentlichen besteht die Rolle des Typescript-Compilers nur darin, Javascript aus Typescript zu generieren.
Pac0
6
@ Pac0 Ich könnte hier etwas falsch verstehen, aber wenn TypeScript zu JavaScript Transpilation ist, wäre GCC dann kein C-to-Machine-Code-Transpiler? Wie würden Sie den Unterschied zwischen einem Transpiler und einem Compiler definieren?
11684
24
Transpiler sind Compiler
user253751
5
Siehe Was meinen die Leute, wenn sie "Transpiler" sagen? (und das Follow-up "Meine ersten fünfzehn Compiler" ) (von jemandem, der am Compiler arbeitet), der argumentiert, dass "Compiler" ein gutes Wort für solche Dinge ist.
ShreevatsaR
2
Javascript selbst wird immer noch interpretiert, oder? - nicht mehr, es wird im
laufenden Betrieb

Antworten:

92

Sie gehen davon aus, dass beim Kompilieren der Quellcode verwendet und Maschinencode, Low-Level-Codes usw. erstellt werden. Beim Kompilieren wird jedoch nur ein Quellcode verwendet und in einen anderen umgewandelt. Es erscheint also vernünftig zu sagen, dass das Verwenden von Typescript und das Erstellen von JavaScript eine Form des Kompilierens ist. Es ist nicht unähnlich zu dem, was (zum Beispiel) c # tut, 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 angesehen werden. Eine (reine) kompilierte Sprache wandelt jedoch (normalerweise) eine Hochsprache in eine Sprache auf niedriger (er) Ebene (näher am Maschinencode) um, wie im Beispiel C #. 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 andere 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 eigenständige (und verwendete) Programmiersprache ist.

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

Liam
quelle
12
Ist JavaScript nicht streng niedriger als TypeScript?
Bergi
3
Obwohl alles in dieser Antwort korrekt und hilfreich ist, zumal die Definition des Kompilierens immer verwirrend ist, beantwortet sie die Frage im Titel nicht. Diese Antwort bezieht sich nur auf TypeScript, während sich die Frage auf Angular bezieht. Der Unterschied ist riesig. Es ist durchaus möglich, Angular zu verwenden, ohne zu wissen, dass TS eine Sache ist. Ich bin überrascht, dass diese Antwort akzeptiert wurde.
Pedro A
3
Ein Compiler muss im Wesentlichen das gesamte Programm verstehen, um ein anderes Programm zu generieren (das normalerweise dasselbe tut, jedoch in einer anderen Sprache - dies schließt Maschinencode ein).
Thorbjørn Ravn Andersen
8
Ich habe das nur zweimal gelesen und konnte hier keine Antwort auf die Frage finden. Die Antwort ist unten.
Kuncevic.dev
5
Die implizite Frage, die das OP stellte, weshalb sie dies akzeptierten, lautete: "Ist es richtig, den Angular-Compiler als Compiler zu bezeichnen?" - und darauf antwortet diese Antwort. Also +1 von mir. Siehe auch Was meinen die Leute, wenn sie "Transpiler" sagen? und das Follow-up "Meine ersten fünfzehn Compiler" .
ShreevatsaR
70

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 es?

Was ist der Unterschied zwischen einem Compiler und einem Transpiler?

@ JörgWMittag hat diese Frage sehr gut beantwortet .

Implementieren Angular und TypeScript Compiler oder Transpiler?

Sowohl TS als auch Angular implementieren echte Compiler. Sie folgen denselben Phasen der lexikalischen Analyse, Analyse, semantischen Analyse und Codegenerierung wie C / C ++ - Compiler, die Assemblycode erzeugen (außer wahrscheinlich zur Optimierung). Sie können sehen, dass die Klasse / der Ordner sowohl in Angular als auch in TS "Compiler" heißt .

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

Gibt es einen separaten Angular-Compiler? Was kompiliert es?

Angular hat zwei Compiler:

  • Compiler anzeigen
  • Modul-Compiler

Die Aufgabe des Ansichts-Compilers besteht darin, die für die Komponentenvorlage angegebene Vorlage in die interne Darstellung einer Komponente umzuwandeln, bei der es sich um eine Ansichtsfactory handelt, die dann zum Instanziieren einer Ansichtsinstanz verwendet wird .

Neben der Transformation der Vorlage kompiliert der Ansichts-Compiler auch verschiedene Metadateninformationen in Form von Dekoratoren wie @HostBinding:@ViewChild usw.

Angenommen, Sie definieren eine Komponente und ihre Vorlage folgendermaßen:

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

Mit 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 Komponentenansicht und wird beim Instanziieren der Komponente verwendet. Der erste Knoten ist die Elementdefinition und der zweite ist 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:

Max Koretskyi
quelle
1
@ Codepleb, siehe diese Antwort von Bergi
Max Koretskyi
1
@codepleb Beachten Sie, dass GCC und viele andere Compiler überhaupt keinen Maschinencode erzeugen. In der Praxis ruft GCC die Systeme automatisch auf, um Maschinencode zu erstellen. Der Code, den es ohne externe Hilfe erstellt, ist jedoch lediglich eine Assembly, die dann an einen externen Assembler übergeben wird.
Prosfilaes
7
@codepleb Diese Antwort ist weit überlegen und beantwortet tatsächlich Ihre Frage. Es ist noch Zeit, Ihr ursprüngliches Urteil zu überdenken.
Async
3
@codepleb Es gibt keinen guten Grund dafür, dass der Begriff "Transpiler" existiert oder jemals existiert hat. Alles, was er tut, ist irreführend.
Leushenko
2
@stom, sorry, diese Frage ist zu weit gefasst. Die am besten bewertete Antwort ist jedoch ziemlich gut
Max Koretskyi
54

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

Kompilieren bedeutet, ein in einer Sprache A geschriebenes Programm in ein in Sprache B geschriebenes semantisch äquivalentes Programm umzuwandeln, so dass die Bewertung des kompilierten Programms gemäß den Regeln der Sprache B (z. B. Interpretation mit einem Interpreter für B ) das gleiche Ergebnis liefert und das gleiche Ergebnis erzielt Die gleichen Nebenwirkungen wie bei der Bewertung des ursprünglichen Programms gemäß den Regeln der Sprache A (z. B. Interpretation mit einem Interpreter für A ).

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

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

  • Wenn A als Assemblersprache und B als Maschinensprache wahrgenommen wird, nennen wir es Assembler .
  • Wenn A als Maschinensprache und B als Assemblersprache wahrgenommen wird, nennen wir es Disassembler .
  • Wenn A als niedriger als B wahrgenommen wird, nennen wir es einen Dekompiler .
  • Wenn A und B dieselbe Sprache sind und das resultierende Programm auf irgendeine Weise schneller oder leichter ist, nennen wir es einen Optimierer .
  • Wenn A und B die gleichen Sprachen sind und das resultierende Programm kleiner ist, nennen wir es einen Minifier .
  • Wenn A und B die gleichen Sprachen sind und das resultierende Programm weniger lesbar ist, nennen wir es einen Verschleierer .
  • Wenn A und B ungefähr auf der gleichen Abstraktionsebene wahrgenommen werden, nennen wir es einen Transpiler , und
  • Wenn A und B als ungefähr auf derselben Abstraktionsebene wahrgenommen werden und das resultierende Programm Formatierungen, Kommentare und Programmiererabsichten beibehält, so dass es möglich ist, das resultierende Programm auf dieselbe Weise wie das ursprüngliche Programm beizubehalten, rufen wir auf Es ist 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 gerade sind .

Zusammenstellung und Interpretation sind Merkmale eines Compilers oder Interpreters (duh!). Jede Sprache kann mit einem Compiler implementiert werden und jede Sprache kann mit einem Interpreter implementiert werden. Viele Sprachen haben sowohl Compiler als auch Interpreter. Viele moderne Hochleistungs-Ausführungs-Engines haben sowohl mindestens einen Compiler als auch 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 keine Implementierung haben. 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 irgendwann interpretiert wird : Wenn Sie etwas ausführen möchten, müssen Sie es interpretieren. Die Kompilierung übersetzt nur Code von einer Sprache in eine andere. Es läuft nicht. Deutung läuft es. (Wenn ein Interpreter in Hardware implementiert ist, nennen wir ihn manchmal "CPU", aber es ist immer noch ein Interpreter.)

Ein typisches Beispiel: Jede einzelne 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. Jetzt gibt es zwei Compiler: einen kompakten Compiler, der mäßig optimierten Code erzeugt, aber der Compiler selbst ist sehr schnell und benötigt wenig RAM. Dieser Compiler fügt auch Profilierungscode in den kompilierten Code ein. Der zweite Compiler ist ein schwererer, langsamerer und teurerer Compiler, der jedoch viel engeren, viel schnelleren Code erzeugt. Außerdem werden die Ergebnisse des vom ersten Compiler eingefügten Profilierungscodes verwendet, um dynamische Optimierungsentscheidungen zu treffen. Außerdem wird die Entscheidung, welcher Code mit dem zweiten Compiler neu kompiliert werden soll, basierend auf diesen Profilinformationen getroffen. Beachten Sie, dass zu keinem Zeitpunkt ein Dolmetscher beteiligt ist. V8 interpretiert nie, es wird immer kompiliert. Tut es nicht' Es enthält nicht einmal einen Dolmetscher. (Eigentlich glaube ich heutzutage, ich beschreibe die ersten beiden Iterationen.)

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

Fast alle JavaScript-Ausführungs-Engines (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 umschaltet.

Sie haben in einem Kommentar geschrieben:

Ich dachte wirklich, dass Maschinencode irgendwo involviert ist.

Was bedeutet "Maschinencode" überhaupt?

Was ist die Maschinensprache eines Mannes, ist die Zwischensprache eines anderen Mannes und umgekehrt? Zum Beispiel gibt es CPUs , die JVM - Bytecode nativ ausführen kann, auf eine solche CPU, JVM - Bytecode ist nativen Maschinencode. Und es gibt Dolmetscher für x86 - Maschinencode, wenn Sie von diesem x86 Maschinencode ausgeführt werden Bytecode interpretiert.

Es gibt einen x86-Interpreter namens JPC, der in Java geschrieben ist. Wenn ich x86-Maschinencode auf einem JPC ausführe, der auf einer nativen JVM-CPU ausgeführt wird… welcher Bytecode und welcher nativer Code? Wenn ich x86-Maschinencode in JavaScript kompiliere (ja, es gibt Tools, die das können) und ihn in einem Browser auf meinem Telefon (mit einer ARM-CPU) ausführe, welcher Bytecode und welcher native Maschinencode? Was ist, wenn das Programm, das ich kompiliere, ein SPARC-Emulator ist und ich ihn zum Ausführen von SPARC-Code verwende?

Beachten Sie, dass jede Sprache eine abstrakte Maschine induziert und Maschinensprache für diese Maschine ist. Daher ist jede Sprache (einschließlich sehr hoher Sprachen) nativer Maschinencode. Sie können auch einen Dolmetscher für jede Sprache schreiben. Daher ist jede Sprache (einschließlich x86-Maschinencode) nicht muttersprachlich.

Jörg W Mittag
quelle
4
+1 für die ausführliche Erklärung des Konzepts der Zusammenstellung, und wenn ich könnte, eine weitere +1 für diese Aufzählungspunkte. Sehr hilfreich.
Pedro A
1
Obwohl ich technisch gesehen die Frage im Titel nicht beantworten muss ... Trotzdem eine verdiente +1 von mir!
Pedro A
Ich bin damit einverstanden, dass es implizit ist, aber die Antwort auf die Frage im Titel lautet "Alles, was das OP als Nicht-Kompilierung auflistet, ist das, was Winkelkompilierung ist".
Jörg W Mittag
Wirklich gute Erklärung, wie es eigentlich um Namenskonventionen geht und nicht um wesentliche Unterschiede. Könnte vielleicht durch die Erwähnung von Mikrocode verbessert werden - um darauf hinzuweisen, dass Sie selbst auf der Ebene des Maschinencodes nicht "am Metall" sind ...
AakashM
1
Ich erinnere mich irgendwie, dass ich gelernt habe, was ein Compiler ist. Wenn mir damals jemand gesagt hätte, dass "Compiler" ein Synonym für "Übersetzer für Code" ist, wäre es viel einfacher gewesen, herauszufinden, wofür es ist oder warum wir es brauchen. Sicher, das klingt heutzutage lächerlich, aber das sagt mir noch einmal, wie viel man davon profitieren kann, wenn man nur die richtige Person hat, die ihm etwas beibringt. Danke dir. :)
Codepleb
18

Das Ausführen des von Ihnen geschriebenen Codes in einem Browser umfasst zwei Dinge:

1) Transpilieren des Typoskripts in JavaScript . Dies ist eine Art gelöstes Problem. Ich denke, sie benutzen nur Webpack.

2) Kompilieren der Winkelabstraktionen in JavaScript . Ich meine Dinge wie Komponenten, Rohre, Anweisungen, Vorlagen usw. Daran arbeitet das eckige Kernteam.

Für den Fall, dass Sie wirklich an diesem zweiten Bit, dem Angular Compiler, interessiert sind, erklärt der Compilerautor Tobias Bosch den Angular Compiler auf der AngularConnect 2016 .

Ich denke, hier herrscht ein wenig Verwirrung zwischen Transpilieren und Kompilieren. Es spielt keine Rolle und ist eine Frage des persönlichen Geschmacks, beide transformieren sich nur zwischen Darstellungen von Code. Aber die Definition, die ich persönlich verwende, ist, dass die Transpilation zwischen zwei verschiedenen Sprachen auf einer ähnlichen Abstraktionsebene stattfindet (z. B. Typoskript zu Javascript), während die Kompilierung einen Schritt nach unten in der Abstraktionsebene erfordert. Ich denke, von Vorlagen, Komponenten, Pipes, Direktiven usw. bis hin zu Javascript ist dies ein Schritt auf der Abstraktionsleiter, und deshalb wird es als Compiler bezeichnet.

Nathan Cooper
quelle
1

Angular Compiler

Eine der wichtigsten Änderungen von Angular 4 zu 5 ist, dass der Compiler schneller und gründlicher umgeschrieben wurde. In der Vergangenheit verwendeten Angular-Anwendungen die sogenannte Just-in-Time-Kompilierung (JIT), bei der die Anwendung zur Laufzeit im Browser vor der Ausführung kompiliert wurde. Die Compiler-Updates in Angular 5 haben die Umstellung auf AOT vorangetrieben, wodurch die App schneller ausgeführt wurde, da beim Ausführen der App weniger Kompilierung durchgeführt wird. AOT wird seit der Version 1.5 der Angular CLI standardmäßig in jedem Produktions-Build aktiviert.

Angenommen, wir möchten eine Anwendung für die Bereitstellung erstellen und den folgenden Befehl ausführen:

ng build --prod

Ein paar Dinge passieren: Produktionsversion, Minimierung, Bündelung von Assets, Dateinamen-Hashing, Baumschütteln, AOT ... (wir können dies mithilfe von Flags aktivieren / deaktivieren, z. B. aot = false). Kurz gesagt, das prod-Flag erstellt ein optimiertes Bundle der Anwendung, indem eine AOT-Kompilierung mit ngc (dem Angular-Compiler) durchgeführt wird, um optimierten Code für den Browser zu erstellen ( Ja, es werden Vorlagen vorkompiliert ).

TypeScript-Compiler

Der TypeScript-Compiler tsc ist für das Kompilieren von TypeScript-Dateien verantwortlich. Es ist der Compiler, der für die Implementierung von TypeScript-Funktionen wie statischen Typen verantwortlich ist. Das Ergebnis ist reines JavaScript, aus dem die TypeScript-Schlüsselwörter und -Ausdrücke entfernt wurden.

Der TypeScript-Compiler verfügt über zwei Hauptfunktionen: Er ist ein Transpiler und eine Typprüfung. Der Compiler transpiliert TypeScript in JavaScript. Es führt die folgenden Transformationen für Ihren Quellcode durch:

  • Entfernen Sie alle Typanmerkungen.
  • Kompilieren Sie neue JavaScript-Funktionen für alte JavaScript-Versionen.
  • Kompilieren Sie TypeScript-Funktionen, die kein Standard-JavaScript sind.

Beim Aufrufen sucht der Compiler nach Konfigurationen, die in tsconfig.json geladen sind (Eine detaillierte Liste aller Compileroptionen sowie Standardwerte finden Sie hier ).

In den meisten Fällen funktioniert der TypeScript-Compiler wie jeder Compiler. Es gibt jedoch einen Unterschied, der das Unvorsichtige erkennen kann: Standardmäßig gibt der Compiler weiterhin JavaScript-Code aus, selbst wenn ein Fehler auftritt. Glücklicherweise kann dieses Verhalten deaktiviert werden, indem die noEmitOnErrorKonfigurationseinstellung in der Datei tsconfig.json auf true gesetzt wird.

Zu beachten : tsc und ngc haben unterschiedliche Zwecke und es geht nicht darum, einen über den anderen auszuwählen. Diese Antwort könnte von Interesse sein .

Diese Antwort wurde basierend auf dem Inhalt der folgenden Bücher erstellt

  • Cloe, M. (2018). "Angular 5-Projekte: Erfahren Sie, wie Sie mit mehr als 70 Projekten einseitige Webanwendungen erstellen".

  • Dewey, B., Grossnicklaus, K., Japikse, P. (2017). "Erstellen von Webanwendungen mit Visual Studio 2017: Verwenden von .NET Core und modernen JavaScript-Frameworks".

  • Freeman, A. (2019). "Essential TypeScript: Vom Anfänger zum Profi".

  • Ghiya, P. (2018). "TypeScript Microservices".

  • Iskandar, A., Chivukulu, S. (2019). "Webentwicklung mit Angular und Bootstrap - Dritte Ausgabe".

  • Hennessy, K., Arora, C. (2018). "Winkel 6 durch Beispiel".

  • Jansen, R., Wolf, I., Vane, V. (2016). "TypeScript: Moderne JavaScript-Entwicklung".

  • Mohammed, Z. (2019). "Winkelprojekte".

  • Seshadri, S. (2018). "Angular: In Betrieb".

  • Wilken, J. (2018). "Winkel in Aktion".

Tiago Martins Peres 李大仁
quelle