Ivy is still in Beta and is not feature complete. So it won’t be there in Angular v6 by default. Ivy is going to be smaller, faster, and simpler. In fact, early demos by Rob Wormald and Igor Minar of a “Hello, World” application are an incredibly tiny 3.2KB!
The theme of smaller, faster, and simpler applies not only to bundle sizes, but also to the compilation process. This is mainly due to two key concepts: locality and tree-shaking.
When we combine the two, we end up with:
- Smaller builds
- Faster rebuild times
- Faster development
- A simpler, more hackable pipeline
- Human readable code
Locality means that Ivy compiles one file at a time. It only looks at a component and its template, not its dependencies, when generating the output. Compiling one file at a time will mean smaller sets of instructions, and it will also mean we’ll be able to do incremental builds. Renderer2 was unable to do this, because it needed to do a static analysis of all code and generate a file called metadata.json that could be used to generate the compilation instructions. This template data was then sent to the Angular interpreter in order to be translated into something readable by the DOM. Ivy compresses these steps, and the template HTML is turned into instructions that are then readable by then DOM.
Locality translates into several benefits. In addition to faster compilation and the lack of a metadata.json step, this simplified process means that library creators will be able to ship AoT (ahead of time compiled) code through npm. Essentially, we’ll have an equivalence between AoT and JIT (just in time). That’s great news for developers – one of the early frustrations with the AoT compiler and renderer was that, often, template code that worked in JIT would not compile with AoT.
One last benefit of locality is that there’s more opportunity for meta-programming, like higher order components and the ability to dynamically generate modules, components, or pipes. Not everyone will need this kind of advanced functionality, but it’s a further step in making Angular a more sophisticated platform.
Ivy has been designed from the start with tree-shaking in mind. “Tree-shaking” means removing unused pieces of your code, which results in smaller bundles and faster load times.
Tree-shaking is done using static analysis, which doesn’t actually run your code. Because of this, it must take into account all possible scenarios and include anything that might be needed in the bundle. For example, if you’ve imported a function but hidden it behind a false conditional, that function will still get included in the bundle, even though it’s never called. Ivy has been designed with this in mind. In Renderer2, the code was similar to a series of conditionals that would include different parts of Angular if they were found in your application. Ivy, on the other hand, breaks things down into smaller, more atomic functions. These atomic functions make the renderer code much more friendly to tree-shaking, because they generate only the code you need from the template you’ve written.
To put it simply: Ivy makes sure that, if you’re not using something in Angular, it doesn’t get included. The tree-shakable features of Angular include:
- Template syntax
- Dependency injection
- Content projection
- Structural directives
- Lifecycle hooks
Currently in Renderer2 pipeline, the template HTML that we write runs through the Angular compiler and generates highly optimised JS code that represents the structure of your template. At runtime, this data structure is passed to the Angular interpreter, which uses the data to determine how to create the DOM.
In Ivy, instead of generating template data and passing it into an interpreter that then makes decisions on which operations to run ,we generate a set of template instructions directly. These instructions will do the work of creating the correct DOM on their own. So we no longer need an interpreter that will check whether every operation is needed.
Renderer2 does static analysis of all code and generate a file called metadata.json that could be used to generate the compilation instructions. This template data was then sent to the Angular interpreter in order to be translated into something readable by the DOM. Ivy compresses these steps, and the template HTML is turned into instructions that are then readable by DOM.
Angular has introduced two compiler entry-points, ngtscand ngcc.
- ngcc (Ng Compatibility Compiler): ngccis designed to process code coming from NPM modules and produce the equivalent Ivy version, as if the code was compiled with ngtsc . It will operate given a node_modules directory and a set of packages to compile, and will produce an equivalent directory from which the Ivy equivalents of those modules can be read. ngcc is a separate script entry point to @angular/compiler-cli.
Ivy Compilation Model
In Ivy model, Angular decorators (@Injectable, etc) are compiled to static properties on the classes (ngInjectableDef). This process takes place without complete analysis of code, and in most cases with a decorator only. Here, the only exception is @Component, which requires knowledge of the meta-data from the @NgModule which declares the component in order to properly generate the ngComponentDef. The selectors which are applicable during compilation of a component template are determined by the module that declares that component.
The information needed by Reference Inversion and type-checking is included in the type declaration of the ngComponentDef in the .d.ts. Here, Reference Inversion is process of determining list of the components, directives, and pipes on which the decorator(which is getting compiled ) depends allowing the module to be ignored altogether
This is the model by which Angular code will be compiled, shipped to NPM, and eventually bundled into applications.
- add enableIvy to src/tsconfig.app.json
- remove BrowserModule from AppModule (workaround for beta.1)
- simplify AppComponent (workaround for beta.1)
- add ngc script into package.json
- set target: es2016 of tsconfig.json (optional)
Angular Compatibility Compiler (ngcc)
The ngcc Angular node_module compatibility compiler – The ngcc is a tool which “upgrades” node_module compiled with non-ivy ngc into ivy compliant format. This compiler will convert node_modules compiled with Angular Compatibility Compiler (ngcc), into node_modules which appear to have been compiled with TypeScript compiler or TSC compiler transformer (ngtsc) and this compiler conversions will allow such “legacy” packages to be used by the Ivy rendering engine.
TSC transformer which removes and converts @Pipe, @Component, @Directive and @NgModule to the corresponding definePipe, defineComponent, defineDirective and defineInjector.