What does the angular compiler "compile"?
Asked Answered
H

5

94

I was asked that today and was not able to give a proper answer.

Typescript transpiles to JS. Then there is tree shaking, "less" (optional) and what else in the process of making a deployment. But nothing like that (afaik) has anything to do with "compiling". Everything gets bundled and heavily optimized, but it's not actually compiled, right?

There is even an "ahead of time"-compiler, which really does a noticeable job. What do I miss?

Javascript itself is still interpreted, right?

Hermaphrodite answered 10/10, 2017 at 15:22 Comment(8)
I agree with the "not really compiling". Essentially, it is a matter of definition of compilation. Some prefer use the word transpilation to mark the transformation from TypeScript to JavaScript. But yeah, in essence, the role of the Typescript compiler is just to generate Javascript from Typescript.Winola
Have a look at Is Babel a compiler or transpiler?Rainband
@Winola I might be misunderstanding something here, but if TypeScript to JavaScript is transpilation, wouldn’t GCC be a C to machine code transpiler? How would you define the difference between a transpiler and a compiler?Jassy
transpilers are compilersChristie
See What do people mean when they say "transpiler"? (and the followup “My first fifteen compilers”) (from someone who works on compiler), which argues that “compiler” is a good word to use for things like this.Michealmicheil
Javascript itself is still intepreted, right? - not any more, it's compiled into machine code on the fly by V8 engineKaiserslautern
Also the horrible expression "tree shaking" just mean dead code elimination (or removal). Using the latter will fetch more results on google... and is also way way clearer.Nowt
@Nowt I'd argue that tree shaking specifically targets the elimination of dead module imports - but you're right, the boundary is fuzzy as well and might lead to the same harm as the com/trans-piler distinction.Rainband
C
96

You're presuming compiling means taking the source code and producing machine code, low-level codes, etc. But compiling actually just means taking one source code and turning it into another. So it seems reasonable to say that taking Typescript and producing JavaScript is a form of compiling. It's not dissimilar to what (for example) c# does when its compiled into IL language.

That said, I'd say a better word for this is Transpiling. I'd suggest that the Typescript compiler is better described as a Transpiler.

The difference is subtle and a transpiler can be thought of as a type of compiler; but a (pure)compiled language is (usually) turning a high-level language to a low(er) level language (nearer to machine code), like the C# example. A transpiler turns a high-level language into a similar level (of abstraction) language (also high level).*

The result of the compiled code is typically not a language that you would write yourself. The result of a transpiler is another high-level language. In theory, you could write IL (as an example) but it's really designed to be produced by a compiler and there are no tools or support for doing this, you produce IL by compiling C#/vb.net, only. Whereas Javascript is a usable (and used) programming language in its own right.

*Lots of caveats as the definitions of these words and their usage are pretty vague

Caber answered 10/10, 2017 at 15:33 Comment(7)
Isn't JavaScript strictly lower level than TypeScript?Rainband
Although everything in this answer is correct and helpful, especially since the definition of compiling is always a matter of confusion, it does not answer the question in title. This answer talks about TypeScript only, while the question is about Angular. The difference is huge. It's totally possible to use Angular without even knowing that TS is a thing. I'm surprised this answer was accepted.Pelion
A compiler needs to essentially understand the whole program in order to generate another program (which usually does the same thing but in another language - this includes machine code).Fango
I just read that twice and could not find the answer to the question here. The answer is just down below.Ethbin
The implicit question that the OP was asking, which is why they accepted this, was “is it correct to call the Angular compiler a compiler?” — and that is what this answer answers. So +1 from me. See also What do people mean when they say "transpiler"? and the followup “My first fifteen compilers”.Michealmicheil
"Transpiling" is never a useful word. The only thing it achieves is to lead to misconceptions like the one in the OP. Avoid at all costs and refer to these things properly: as compilers.Tumble
@Michealmicheil Exactly. I'm not a native speaker, and what I think is not 100% what I can manifest into words, especially in another language. But the thing Liam explained here was exactly the root of what confused me. Sorry to the people do not agree. Looking at it now, I see how this is a bit confusing.Hermaphrodite
K
72

You seem to be asking three questions in one:

  • What is the difference between a compiler and a transpiler?
  • Do Angular and TypeScript implement compilers or transpilers?
  • Is there a separate Angular compiler? What does it compile?

What is the difference between a compiler and transpiler?

@JörgWMittag provided a very good answer to this question.

Do Angular and TypeScript implement compilers or transpilers?

Both TS and Angular implement real compilers. They follow the same stages of lexical analysis, parsing, semantic analysis, and code generation as C/C++ compilers that produce assembly code (except probably for optimization). You can see that the class/folder are named "compiler" in both Angular and TS.

The angular compiler is not really related to TypeScript compiler. These are very different compilers.

Is there a separate Angular compiler? What does it compile?

Angular has two compilers:

  • View Compiler
  • Module Compiler

The job of the view compiler is to transform the template you specify for the component template into the internal representation of a component which is a view factory that is then used to instantiate a view instance.

Besides transforming the template, the view compiler also compiles various metadata information in the form of decorators like @HostBinding, @ViewChild etc.

Suppose you define a component and its template like this:

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

Using this data the compiler generates the following slightly simplified component factory:

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

It describes the structure of a component view and is used when instantiating the component. The first node is element definition and the second one is text definition. You can see that each node gets the information it needs when being instantiated through parameters list. It’s a job of a compiler to resolve all the required dependencies and provide them at the runtime.

I strongly recommend reading these articles:

Also, see the answer to What is the difference between Angular AOT and JIT compiler.

The job of the module compiler is to create a module factory which basically contains merged definitions of the providers.

For more information, read:

Kaiserslautern answered 10/10, 2017 at 16:2 Comment(13)
Alright. In my understanding, a compiler turns "human readable code" into machine code. You say, this is not the case here, it's still interpreted and although all of that, the term "compiler" is correct? If yes, my interpretation of a compiler was wrong. Wikipedia proves you right, but I wonder why the term "transpiler" exists then. It sounds completely obsolete from this point of view. Thanks for your answer and the lecture! :)Hermaphrodite
@codepleb, see this answer by BergiKaiserslautern
@Hermaphrodite Note that GCC and many other compilers don't produce machine code at all. In practice, GCC automatically calls the systems to produce machine code, but the code it produces without external help is merely assembly, which is then handed to an external assembler.Hluchy
@AngularInDepth.com can you shorten the header bar in your web site pls :)Thitherto
@omeralper, what do you mean shorten? what exactly do you find inconvenient?Kaiserslautern
@AngularInDepth.com the header is huge, it makes web site hard to read. Make it single line and remove the footer.Thitherto
@omeralper, angluarindepth.com blog is hosted on the medium.com platform. The customization options are very limited. I can't modify the layout of a headerKaiserslautern
@Hermaphrodite This answer is far superior and actually answers your question. There's still time to reconsider your original judgement.Laud
@Hermaphrodite there's no good reason for the term "transpiler" to exist or ever to have existed, all it does is mislead.Tumble
@Laud The accepted answer answers my question 100% and is more compact than this. I like both of course, but when I search SO for a specific question, I like when the answers I find are short and spot on. I agree that here are very nice examples and everything, but the accepted answer was a direct hit to what I tried to ask. The first sentence was basically the answer I was looking for, and not explanation stuff around the issue, while the answer to the real issue is somewhere "between to be found". I know that this sounds like a lazy excuse, but SO is all about compact/simple/straight imho.Hermaphrodite
Can you answer How Angular builds and runs in depth ? Here is the question.Nailbiting
@stom, sorry, that question is too broad. The most upvoted answer is pretty good thoughKaiserslautern
@AngularInDepth.com , Yes I see :) , if possible you can write your findings in your medium blog , may help others.Nailbiting
G
55

Typescript transpires to JS. Then there is tree shaking, "less" (optional) and what else in the process of making a deployment. But nothing like that (afaik) has anything to do with "compiling". Everything gets bundled and heavily optimized, but it's not actually compiled, right?

Compilation means transforming a program written in a language A into a semantically equivalent program written in language B such that evaluating the compiled program according to the rules of language B (for example interpreting it with an interpreter for B) yields the same result and has the same side-effects as evaluating the original program according to the rules of language A (for example interpreting it with an interpreter for A).

Compilation simply means translating a program from language A to language B. That's all it means. (Also note that it is perfectly possible for A and B to be the same language.)

In some cases, we have more specialized names for certain kinds of compilers, depending on what A and B are, and what the compiler does:

  • if A is perceived to be assembly language and B is perceived to be machine language, then we call it an assembler,
  • if A is perceived to be machine language and B is perceived to be assembly language, then we call it a disassembler,
  • if A is perceived to be lower-level than B, then we call it a decompiler,
  • if A and B are the same language, and the resulting program is in some way faster or lighter, then we call it an optimizer,
  • if A and B are the same languages, and the resulting program is smaller, then we call it a minifier,
  • if A and B are the same languages, and the resulting program is less readable, then we call it an obfuscator,
  • if A and B are perceived to be at roughly the same level of abstraction, then we call it a transpiler, and
  • if A and B are perceived to be at roughly the same level of abstraction and the resulting program preserves formatting, comments, and programmer intent such that it is possible to maintain the resulting the program in the same fashion as the original program, then we call it a re-engineering tool.

Also, note that older sources may use the terms "translation" and "translator" instead of "compilation" and "compiler". For example, C talks about "translation units".

You may also stumble across the term "language processor". This can mean either a compiler, an interpreter, or both compilers and interpreters depending on the definition.

Javascript itself is still interpreted, right?

JavaScript is a language. Languages are a set of logical rules and restrictions. Languages aren't interpreted or compiled. Languages just are.

Compilation and interpretation are traits of a compiler or interpreter (duh!). Every language can be implemented with a compiler and every language can be implemented with an interpreter. Many languages have both compilers and interpreters. Many modern high-performance execution engines have both at least one compiler and at least one interpreter.

These two terms belong on different layers of abstraction. If English were a typed language, "interpreted-language" would be a type error.

Note also that some languages have neither an interpreter nor a compiler. There are languages which have no implementation at all. Still, they are languages, and you can write programs in them. You just can't run them.

Also, note that everything is interpreted at some point: if you want to execute something, you must interpret it. Compilation just translates code from one language to another. It doesn't run it. Interpretation runs it. (Sometimes, when an interpreter is implemented in hardware, we call it a "CPU", but it's still an interpreter.)

Case in point: every single currently existing mainstream JavaScript implementation has a compiler.

V8 started out as a pure compiler: it compiled JavaScript straight to moderately optimized native machine code. Later, a second compiler was added. Now, there are two compilers: a lightweight compiler that produces moderately optimized code but the compiler itself is very fast and uses little RAM. This compiler also injects profiling code into the compiled code. The second compiler is a more heavyweight, slower, more expensive compiler, which, however, produces much tighter, much faster code. It also uses the results of the profiling code injected by the first compiler to make dynamic optimization decisions. Also, the decision which code to re-compile using the second compiler is made based on that profiling information. Note that at no time there is an interpreter involved. V8 never interprets, it always compiles. It doesn't even contain an interpreter. (Actually, I believe nowadays it does, I am describing the first two iterations.)

SpiderMonkey compiles JavaScript to SpiderMonkey bytecode, which it then interprets. The interpreter also profiles the code, and then the code which gets executed most often is compiled by a compiler to native machine code. So, SpiderMonkey contains two compilers: one from JavaScript to SpiderMonkey bytecode, and another from SpiderMonkey bytecode to native machine code.

Almost all JavaScript execution engines (with the exception of V8) follow this model of an AOT compiler that compiles JavaScript to bytecode, and a mixed-mode engine that switches between interpreting and compiling that bytecode.

You wrote in a comment:

I really was thinking that machine code is somewhere involved.

What does "machine code" even mean?

What is one man's machine language is another man's intermediate language and vice versa? For example, there are CPUs which can natively execute JVM bytecode, on such a CPU, JVM bytecode is native machine code. And there are interpreters for x86 machine code, when you run of those x86 machine code is interpreted bytecode.

There is an x86 interpreter called JPC written in Java. If I run x86 machine code on JPC running on a native JVM CPU … which is the bytecode and which is the native code? If I compile x86 machine code to JavaScript (yes, there are tools which can do that) and run it in a browser on my phone (which has an ARM CPU), which is the bytecode and which is the native machine code? What if the program I am compiling is a SPARC emulator, and I use it to run SPARC code?

Note that every language induces an abstract machine, and is machine language for that machine. So, every language (including very high-level languages) is native machine code. Also, you can write an interpreter for every language. So, every language (including x86 machine code) is not-native.

Glidewell answered 10/10, 2017 at 21:7 Comment(6)
+1 for the deep explanation of the concept of compilation, and if I could, another +1 for those bullet points. Very helpful.Pelion
Although, I have to say, technically this does not answer the question in title... Still a deserved +1 from me, though!Pelion
I agree it's implicit, but the answer to the question in the title is "everything the OP lists as not compilation is what angular compilation is".Mercy
Really good explanation of how this is actually about naming conventions rather than substantive difference. Could perhaps be improved by mentioning microcode - to point out that even at the level of machine code, you're not 'at the metal'...Mcclendon
I somehow remember learning what a compiler is. If anyone would have told me back then, that "compiler" is a synonym for "translator for code", it would have been so much easier to get what it's for or why we need it. Sure, this sounds ridiculous from nowadays standpoint, but this just tells me once again how much one can benefit just from having the right person to teach him something. Thank you. :)Hermaphrodite
This is a fantastic answer. Also, I find the term "JVM CPU" quite amusing… who's the virtual machine now?Sollie
M
19

Getting the code you've written to run on a browser involves two things:

1) Transpiling the Typescript into JavaScript. This is kind of a solved problem. I think they just use webpack.

2) Compiling the angular abstractions into JavaScript. I mean things like a components, pipes, directives, templates etc. This is what the angular core team work on.

In case you're really interested in that second bit, the angular compiler, watch compiler author Tobias Bosch explain the Angular Compiler at AngularConnect 2016.

I think there's a bit of confusion going on here between transpiling and compilation. It sort of doesn't matter and is a matter of personal taste, they're both just transforms between representations of code. But the definition I personally use is that transpilation is between two different languages at a similar abstraction level (eg typescript to javascript), whereas compilation requires a step down in level of abstraction. I think from templates, components, pipes, directives etc to just javascript is a step down the abstraction ladder, and that's why it's called a compiler.

Margrettmarguerie answered 10/10, 2017 at 15:53 Comment(0)
L
1

Angular Compiler

One of the most important changes from Angular 4 to 5 is that the compiler has been rewritten be faster and more thorough. In the past, Angular applications used what we call Just-in-Time (JIT) compilation, where the application was compiled at runtime in the browser before running. The compiler updates in Angular 5 advanced the move to AOT, which made the app run faster as it performes less compilation when running the app. AOT become enabled by default in any production build since the 1.5 version of the Angular CLI.

Let's say we want to build an application for deployment and run the following command:

ng build --prod

A few things happen: production version, minification, bunddles assets, filename hashing, tree shaking, AOT ... (we can enable/disable this using flags, ex. aot=false). In short, the prod flag creates an optimized bundle of the application by doing AOT compilation using the ngc (the Angular compiler) to create optimized code ready for the browser (Yes, it pre-compiles templates).

TypeScript Compiler

The TypeScript compiler, tsc, is responsible for compiling TypeScript files. It is the compiler that is responsible for implementing TypeScript features, such as static types, and the result is pure JavaScript from which the TypeScript keywords and expressions have been removed.

The TypeScript compiler has two main features: it is a transpiler and a type checker. The compiler transpiles TypeScript to JavaScript. It does the following transformations on your source code:

  • Remove all type annotations.
  • Compile new JavaScript features for old versions of JavaScript.
  • Compile TypeScript features that are not standard JavaScript.

Invoking it, the compiler searches for configurations loaded in tsconfig.json (A detailed list of all the compiler options, along with default values, can be found here).

In most respects, the TypeScript compiler works like any compiler. But there is one difference that can catch out the unwary: by default, the compiler continues to emit JavaScript code even when it encounters an error. Fortunately, this behavior can be disabled by setting the noEmitOnError configuration setting to true in the tsconfig.json file.

To note: tsc and ngc have different purposes and it's not about selecting one over the other. This answer might be of interest.

This answer was crafted based on the content from the following books

  • Cloe, M. (2018). "Angular 5 Projects: Learn to Build Single Page Web Applications Using 70+ Projects".

  • Dewey, B., Grossnicklaus, K., Japikse, P. (2017). "Building Web Applications with Visual Studio 2017: Using .NET Core and Modern JavaScript Frameworks".

  • Freeman, A. (2019). "Essential TypeScript: From Beginner to Pro".

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

  • Iskandar, A., Chivukulu, S. (2019). "Web Development with Angular and Bootstrap - Third Edition".

  • Hennessy, K., Arora, C. (2018). "Angular 6 by Example".

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

  • Mohammed, Z. (2019). "Angular Projects".

  • Seshadri, S. (2018). "Angular: Up and Running".

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

Longsome answered 25/10, 2019 at 9:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.