Cosa "compila" il compilatore angolare?


88

Mi è stato chiesto oggi e non sono stato in grado di dare una risposta adeguata.

Transpiles dattiloscritto a JS. Poi c'è lo scuotimento degli alberi, "less" (opzionale) e cos'altro nel processo di implementazione. Ma niente del genere (afaik) ha a che fare con la "compilazione". Tutto viene raggruppato e fortemente ottimizzato, ma non è effettivamente compilato, giusto?

C'è anche un compilatore "in anticipo sui tempi", che fa davvero un lavoro notevole. Cosa mi manca?

Javascript stesso è ancora interpretato, giusto?


6
Sono d'accordo con la "non proprio compilazione". Essenzialmente, è una questione di definizione di compilazione . Alcuni preferiscono usare la parola transpilation per contrassegnare la trasformazione da TypeScript a JavaScript. Ma sì, in sostanza, il ruolo del compilatore Typescript è solo quello di generare Javascript da Typescript.
Pac0

6
@ Pac0 Potrei fraintendere qualcosa qui, ma se da TypeScript a JavaScript è transpilation, GCC non sarebbe un transpiler da C a codice macchina? Come definiresti la differenza tra un transpiler e un compilatore?
11684

24
i transpiler sono compilatori
user253751

5
Vedi Cosa intendono le persone quando dicono "transpiler"? (e il seguito "I miei primi quindici compilatori" ) (da qualcuno che lavora sul compilatore), che sostiene che "compilatore" è una buona parola da usare per cose come questa.
ShreevatsaR

2
Javascript stesso è ancora interpretato, giusto? - non più, è compilato al volo nel codice macchina dal motore V8
Max Koretskyi

Risposte:


91

Presumi che compilare significhi prendere il codice sorgente e produrre codice macchina, codici di basso livello, ecc. Ma compilare in realtà significa semplicemente prendere un codice sorgente e trasformarlo in un altro. Quindi sembra ragionevole dire che prendere Typescript e produrre JavaScript è una forma di compilazione. Non è dissimile da ciò che (ad esempio) fa c # quando viene compilato in linguaggio IL.

Detto questo, direi che una parola migliore per questo è Transpiling . Suggerirei che il compilatore Typescript sia meglio descritto come Transpiler.

La differenza è sottile e un transpiler può essere pensato come un tipo di compilatore; ma un linguaggio compilato (puro) sta (di solito) trasformando un linguaggio di alto livello in un linguaggio di livello inferiore (più vicino al codice macchina), come nell'esempio C #. Un transpiler trasforma un linguaggio di alto livello in un linguaggio di livello simile (di astrazione) (anche di alto livello). *

Il risultato del codice compilato in genere non è un linguaggio che scriveresti tu stesso . Il risultato di un transpiler è un altro linguaggio di alto livello. In teoria, potresti scrivere IL (come esempio) ma è davvero progettato per essere prodotto da un compilatore e non ci sono strumenti o supporto per farlo, produci IL compilando C # / vb.net, solo. Mentre Javascript è un linguaggio di programmazione utilizzabile (e utilizzato) a sé stante.

* Molti avvertimenti in quanto le definizioni di queste parole e il loro utilizzo sono piuttosto vaghe


12
JavaScript non è di livello strettamente inferiore a TypeScript?
Bergi

3
Sebbene tutto in questa risposta sia corretto e utile, soprattutto perché la definizione di compilazione è sempre una questione di confusione, non risponde alla domanda nel titolo. Questa risposta parla solo di TypeScript, mentre la domanda riguarda Angular. La differenza è enorme. È totalmente possibile usare Angular senza nemmeno sapere che TS è una cosa. Sono sorpreso che questa risposta sia stata accettata.
Pedro A

3
Un compilatore deve essenzialmente comprendere l'intero programma per generare un altro programma (che di solito fa la stessa cosa ma in un altro linguaggio - questo include il codice macchina).
Thorbjørn Ravn Andersen

8
L'ho letto due volte e non sono riuscito a trovare la risposta alla domanda qui. La risposta è appena sotto.
kuncevic.dev

5
La domanda implicita che l'OP stava ponendo, motivo per cui lo hanno accettato, era "è corretto chiamare compilatore Angular un compilatore?" - e questo è ciò che risponde questa risposta. Quindi +1 da me. Vedi anche Cosa intendono le persone quando dicono "transpiler"? e il seguito "I miei primi quindici compilatori" .
ShreevatsaR

70

Sembra che tu stia facendo tre domande in una:

  • Qual è la differenza tra un compilatore e un transpiler?
  • Angular e TypeScript implementano compilatori o transpilatori?
  • Esiste un compilatore angolare separato? Cosa compila?

Qual è la differenza tra un compilatore e un transpiler?

@ JörgWMittag ha fornito un'ottima risposta a questa domanda.

Angular e TypeScript implementano compilatori o transpilatori?

Sia TS che Angular implementano compilatori reali . Seguono le stesse fasi di analisi lessicale, parsing, analisi semantica e generazione di codice dei compilatori C / C ++ che producono codice assembly (tranne probabilmente per l'ottimizzazione). Puoi vedere che la classe / cartella sono denominate "compilatore" sia in Angular che in TS .

Il compilatore angolare non è realmente correlato al compilatore TypeScript. Questi sono compilatori molto diversi.

Esiste un compilatore angolare separato? Cosa compila?

Angular ha due compilatori:

  • Visualizza compilatore
  • Compilatore del modulo

Il compito del compilatore di viste è trasformare il modello specificato per il modello di componente nella rappresentazione interna di un componente che è una fabbrica di viste che viene quindi utilizzata per creare un'istanza di vista .

Oltre a trasformare il modello, il compilatore di viste compila anche varie informazioni sui metadati sotto forma di decoratori come @HostBinding, @ViewChildecc.

Supponiamo di definire un componente e il suo modello in questo modo:

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

Usando questi dati il ​​compilatore genera la seguente fabbrica di componenti leggermente semplificata:

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

Descrive la struttura di una vista del componente e viene utilizzata quando si crea un'istanza del componente. Il primo nodo è la definizione dell'elemento e il secondo è la definizione del testo. Puoi vedere che ogni nodo ottiene le informazioni di cui ha bisogno quando viene istanziato tramite l'elenco dei parametri. È compito di un compilatore risolvere tutte le dipendenze richieste e fornirle in fase di esecuzione.

Consiglio vivamente di leggere questi articoli:

Inoltre, vedere la risposta a Qual è la differenza tra il compilatore Angular AOT e JIT.

Il compito del compilatore di moduli è creare una fabbrica di moduli che fondamentalmente contiene definizioni unite dei provider.

Per ulteriori informazioni, leggi:



1
@codepleb Notare che GCC e molti altri compilatori non producono affatto codice macchina. In pratica, GCC chiama automaticamente i sistemi per produrre codice macchina, ma il codice che produce senza un aiuto esterno è semplicemente un assembly, che viene poi consegnato a un assemblatore esterno.
prosfilaes

7
@codepleb Questa risposta è di gran lunga superiore e risponde effettivamente alla tua domanda. C'è ancora tempo per riconsiderare il tuo giudizio originale.
asincrono

3
@codepleb non c'è una buona ragione per cui il termine "transpiler" esista o sia mai esistito, tutto ciò che fa è fuorviante.
Leushenko

2
@stom, scusa, questa domanda è troppo ampia. La risposta più votata è abbastanza buona però
Max Koretskyi

54

Il dattiloscritto trapela a JS. Poi c'è lo scuotimento degli alberi, "less" (opzionale) e cos'altro nel processo di implementazione. Ma niente del genere (afaik) ha a che fare con la "compilazione". Tutto viene raggruppato e fortemente ottimizzato, ma non è effettivamente compilato, giusto?

Compilazione significa trasformare un programma scritto in una lingua A in un programma semanticamente equivalente scritto in una lingua B tale che valutare il programma compilato secondo le regole del linguaggio B (ad esempio interpretarlo con un interprete per B ) produce lo stesso risultato e ha il stessi effetti collaterali della valutazione del programma originale secondo le regole del linguaggio A (ad esempio interpretarlo con un interprete per A ).

Compilazione significa semplicemente traducendo un programma dal linguaggio A alla lingua B . È tutto ciò che significa. (Notare inoltre che è perfettamente possibile che A e B siano la stessa lingua.)

In alcuni casi, abbiamo nomi più specializzati per certi tipi di compilatori, a seconda di cosa sono A e B e cosa fa il compilatore:

  • se A è percepito come linguaggio assembly e B è percepito come linguaggio macchina, allora lo chiamiamo assemblatore ,
  • se A è percepito come linguaggio macchina e B è percepito come linguaggio assembly, allora lo chiamiamo disassemblatore ,
  • se A viene percepito come di livello inferiore a B , lo chiamiamo decompilatore ,
  • se A e B sono la stessa lingua e il programma risultante è in qualche modo più veloce o più leggero, lo chiamiamo ottimizzatore ,
  • se A e B sono le stesse lingue e il programma risultante è più piccolo, lo chiamiamo minificatore ,
  • se A e B sono le stesse lingue e il programma risultante è meno leggibile, lo chiamiamo offuscatore ,
  • se A e B sono percepiti come all'incirca allo stesso livello di astrazione, allora lo chiamiamo un transpiler , e
  • se A e B sono percepiti all'incirca allo stesso livello di astrazione e il programma risultante conserva la formattazione, i commenti e l'intento del programmatore in modo tale che sia possibile mantenere il programma risultante allo stesso modo del programma originale, allora chiamiamo è uno strumento di reingegnerizzazione .

Inoltre, nota che le fonti più vecchie possono usare i termini "traduzione" e "traduttore" invece di "compilazione" e "compilatore". Ad esempio, C parla di "unità di traduzione".

Potresti anche imbatterti nel termine "elaboratore di linguaggio". Questo può significare un compilatore, un interprete o entrambi compilatori e interpreti a seconda della definizione.

Javascript stesso è ancora interpretato, giusto?

JavaScript è un linguaggio. Le lingue sono un insieme di regole e restrizioni logiche. Le lingue non vengono interpretate o compilate. Le lingue lo sono .

La compilazione e l'interpretazione sono tratti di un compilatore o interprete (duh!). Ogni lingua può essere implementata con un compilatore e ogni lingua può essere implementata con un interprete. Molte lingue hanno sia compilatori che interpreti. Molti motori di esecuzione moderni ad alte prestazioni hanno almeno un compilatore e almeno un interprete.

Questi due termini appartengono a diversi livelli di astrazione. Se l'inglese fosse una lingua digitata, "interpreted-language" sarebbe un errore di tipo.

Nota anche che alcune lingue non hanno né un interprete né un compilatore. Ci sono lingue che non hanno alcuna implementazione. Tuttavia, sono lingue e puoi scrivere programmi in esse. Non puoi semplicemente eseguirli.

Inoltre, nota che tutto viene interpretato a un certo punto : se vuoi eseguire qualcosa, devi interpretarlo. La compilazione traduce semplicemente il codice da una lingua all'altra. Non lo esegue. L'interpretazione lo fa funzionare. (A volte, quando un interprete è implementato nell'hardware, lo chiamiamo "CPU", ma è comunque un interprete.)

Caso in questione: ogni singola implementazione JavaScript mainstream attualmente esistente ha un compilatore.

V8 è iniziato come un compilatore puro: ha compilato JavaScript direttamente in codice macchina nativo moderatamente ottimizzato. Successivamente è stato aggiunto un secondo compilatore. Ora, ci sono due compilatori: un compilatore leggero che produce codice moderatamente ottimizzato ma il compilatore stesso è molto veloce e usa poca RAM. Questo compilatore inietta anche il codice di profilatura nel codice compilato. Il secondo compilatore è un compilatore più pesante, più lento e più costoso, che, tuttavia, produce codice molto più stretto e molto più veloce. Utilizza anche i risultati del codice di profilazione iniettato dal primo compilatore per prendere decisioni di ottimizzazione dinamica. Inoltre, la decisione su quale codice ricompilare utilizzando il secondo compilatore viene presa in base a tali informazioni di profilo. Notare che in nessun momento è coinvolto un interprete. V8 non interpreta mai, compila sempre. Non lo fa Non contengono nemmeno un interprete. (In realtà, credo di sì, sto descrivendo le prime due iterazioni.)

SpiderMonkey compila JavaScript nel bytecode SpiderMonkey, che poi interpreta. L'interprete profila anche il codice, quindi il codice che viene eseguito più spesso viene compilato da un compilatore in codice macchina nativo. Quindi, SpiderMonkey contiene due compilatori: uno da JavaScript a SpiderMonkey bytecode e un altro da SpiderMonkey a codice macchina nativo.

Quasi tutti i motori di esecuzione JavaScript (ad eccezione del V8) seguono questo modello di un compilatore AOT che compila JavaScript in bytecode e un motore a modalità mista che passa dall'interpretazione alla compilazione di quel bytecode.

Hai scritto in un commento:

Stavo davvero pensando che il codice macchina fosse coinvolto da qualche parte.

Cosa significa anche "codice macchina"?

Qual è il linguaggio macchina di un uomo è il linguaggio intermedio di un altro uomo e viceversa? Ad esempio, ci sono CPU che possono eseguire nativamente bytecode JVM, su una tale CPU, bytecode JVM è codice macchina nativo. E ci sono interpreti per il codice macchina x86, quando si esegue di quei codici macchina x86 viene interpretato bytecode.

C'è un interprete x86 chiamato JPC scritto in Java. Se eseguo il codice macchina x86 su JPC in esecuzione su una CPU JVM nativa ... qual è il bytecode e quale è il codice nativo? Se compilo il codice macchina x86 in JavaScript (sì, ci sono strumenti che possono farlo) e lo eseguo in un browser sul mio telefono (che ha una CPU ARM), qual è il bytecode e qual è il codice macchina nativo? E se il programma che sto compilando è un emulatore SPARC e lo utilizzo per eseguire codice SPARC?

Nota che ogni linguaggio induce una macchina astratta, ed è linguaggio macchina per quella macchina. Quindi, ogni lingua (compresi i linguaggi di altissimo livello) è un codice macchina nativo. Inoltre, puoi scrivere un interprete per ogni lingua. Quindi, ogni lingua (incluso il codice macchina x86) non è nativa.


4
+1 per la spiegazione approfondita del concetto di compilazione e, se potessi, un altro +1 per quei punti elenco. Molto utile.
Pedro A

1
Anche se, devo dire, tecnicamente questo non risponde alla domanda nel titolo ... Ancora un meritato +1 da parte mia, però!
Pedro A

Sono d'accordo che sia implicito, ma la risposta alla domanda nel titolo è "tutto ciò che l'OP elenca come non compilazione è ciò che è compilazione angolare".
Jörg W Mittag

Davvero una buona spiegazione di come si tratta in realtà di convenzioni di denominazione piuttosto che di differenze sostanziali. Potrebbe forse essere migliorato menzionando il microcodice - per sottolineare che anche a livello di codice macchina, non sei "al metallo" ...
AakashM

1
In qualche modo ricordo di aver imparato cos'è un compilatore. Se qualcuno mi avesse detto allora che "compilatore" è un sinonimo di "traduttore per codice", sarebbe stato molto più facile ottenere quello che serve o perché ne abbiamo bisogno. Certo, questo suona ridicolo dal punto di vista di oggi, ma questo mi dice ancora una volta quanto si può trarre vantaggio dall'avere la persona giusta che gli insegni qualcosa. Grazie. :)
codepleb

18

Ottenere il codice che hai scritto per essere eseguito su un browser implica due cose:

1) Transpiling del dattiloscritto in JavaScript . Questo è una specie di problema risolto. Penso che usino solo webpack.

2) Compilare le astrazioni angolari in JavaScript . Intendo cose come componenti, tubi, direttive, modelli ecc. Questo è ciò su cui lavora il team angolare.

Nel caso in cui tu sia davvero interessato a quel secondo bit, il compilatore angolare, guarda l'autore del compilatore Tobias Bosch spiegare il compilatore angolare ad AngularConnect 2016 .

Penso che qui ci sia un po 'di confusione tra transpiling e compilation. In un certo senso non ha importanza ed è una questione di gusto personale, entrambi sono solo trasformazioni tra rappresentazioni di codice. Ma la definizione che uso personalmente è che la traspolazione è tra due linguaggi diversi a un livello di astrazione simile (ad esempio da dattiloscritto a javascript), mentre la compilazione richiede un livello di astrazione inferiore. Penso che da modelli, componenti, pipe, direttive ecc. Al solo javascript sia un gradino più in basso nella scala di astrazione, ed è per questo che si chiama compilatore.


1

Compilatore angolare

Uno dei cambiamenti più importanti da Angular 4 a 5 è che il compilatore è stato riscritto in modo più veloce e completo. In passato, le applicazioni Angular utilizzavano quella che chiamiamo compilazione Just-in-Time (JIT), in cui l'applicazione veniva compilata in fase di esecuzione nel browser prima di essere eseguita. Gli aggiornamenti del compilatore in Angular 5 hanno avanzato il passaggio ad AOT, che ha reso l'app più veloce poiché esegue meno compilazioni durante l'esecuzione dell'app. AOT viene abilitato per impostazione predefinita in qualsiasi build di produzione dalla versione 1.5 di Angular CLI.

Supponiamo di voler creare un'applicazione per la distribuzione ed eseguire il seguente comando:

ng build --prod

Succedono alcune cose: versione di produzione, minification, bundle assets, filename hashing, tree shaking, AOT ... (possiamo abilitarlo / disabilitarlo usando flag, es. Aot = false). In breve, il flag prod crea un bundle ottimizzato dell'applicazione eseguendo la compilazione AOT utilizzando ngc (il compilatore Angular) per creare codice ottimizzato pronto per il browser ( Sì, precompila i modelli ).

TypeScript Compiler

Il compilatore TypeScript, tsc , è responsabile della compilazione dei file TypeScript. È il compilatore responsabile dell'implementazione delle funzionalità TypeScript, come i tipi statici, e il risultato è JavaScript puro da cui sono state rimosse le parole chiave e le espressioni TypeScript.

Il compilatore TypeScript ha due caratteristiche principali: è un transpiler e un controllo di tipo. Il compilatore trasporta TypeScript in JavaScript. Esegue le seguenti trasformazioni sul codice sorgente:

  • Rimuovi tutte le annotazioni di tipo.
  • Compilare nuove funzionalità JavaScript per le vecchie versioni di JavaScript.
  • Compilare le funzionalità TypeScript che non sono JavaScript standard.

Invocandolo, il compilatore cerca le configurazioni caricate in tsconfig.json (un elenco dettagliato di tutte le opzioni del compilatore, insieme ai valori predefiniti, può essere trovato qui ).

Per molti aspetti, il compilatore TypeScript funziona come qualsiasi compilatore. Ma c'è una differenza che può catturare gli incauti: per impostazione predefinita, il compilatore continua a emettere codice JavaScript anche quando incontra un errore. Fortunatamente, questo comportamento può essere disabilitato impostando l' noEmitOnErrorimpostazione di configurazione su true nel file tsconfig.json.

Da notare : TSC e NGC hanno scopi diversi e non è sulla selezione di uno sopra l'altro. Questa risposta potrebbe interessarti .

Questa risposta è stata elaborata in base al contenuto dei seguenti libri

  • Cloe, M. (2018). "Progetti Angular 5: impara a creare applicazioni Web su una pagina utilizzando oltre 70 progetti".

  • Dewey, B., Grossnicklaus, K., Japikse, P. (2017). "Creazione di applicazioni Web con Visual Studio 2017: utilizzo di .NET Core e framework JavaScript moderni".

  • Freeman, A. (2019). "Essential TypeScript: dal principiante al professionista".

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

  • Iskandar, A., Chivukulu, S. (2019). "Sviluppo Web con Angular e Bootstrap - Terza Edizione".

  • Hennessy, K., Arora, C. (2018). "Angolare 6 per esempio".

  • Jansen, R., Wolf, I., Vane, V. (2016). "TypeScript: Modern JavaScript Development".

  • Mohammed, Z. (2019). "Progetti angolari".

  • Seshadri, S. (2018). "Angular: attivo e funzionante".

  • Wilken, J. (2018). "Angular in Action".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.