First, let’s understand a few key terms and I will also include references to articles if you need a deeper understanding of these concepts:
I am sure most of us have come across articles, blogs comparing the final bundle (compiled JS) sizes of a Hello-World or ToDo app written in modern JS frameworks/libraries and would notice that an app written in Angular would relatively have bigger bundle size. The bundle size was definitely a cause of concern, especially when we are moving towards mobile-first and high-performance apps. We know that the Angular framework consists of many libraries such as i18n, Http, router, animations, etc. and before Ivy, the Angular renderer (ViewEngine) itself was not tree-shakable. So the entire ViewEngine renderer was being shipped to the browser and was contributing towards the bundle size. The idea of reducing the framework size itself by not including the unused code in the final bundle and also making the renderer tree-shakable led to the new default compiler and renderer mechanism known as Ivy.
Ivy runtime is based on the concept of Incremental DOM and generates a series of instructions to update the DOM trees. Ivy generates these instructions (Template Instructions) by going through the Template code that you have written and these instructions are self-sufficient to create/update DOM without the need of any Angular Interpreter. This means that you do not need to bundle the entire Angular Interpreter code in the final generated bundle file, or in other words, using these template instructions set, you are only generating code (in the final bundle) that you need from the template, that you have written.
For example, if you do not use Pipe in your template, there won’t be an instruction set (in compiled JS) related to CreatePipe() and hence that code can easily be tree shaken from Angular Core code by tools such as WebPack or Rollup, etc.