angular/angular
From View Engine to Ivy
The compiler and runtime rewrite that defined the v9 release. The transition spans roughly Dec 2017 (the first commits) through Feb 2020 (Ivy as the default) and v13 (final removal of View Engine).
What View Engine was
The pre-v9 compiler was called View Engine (VE). For each component it generated an .ngfactory.ts file that built the component's view at runtime via a fixed runtime imported from @angular/platform-browser-dynamic (JIT) or compiled into AOT factories.
VE worked but had structural problems:
- Bundle size. The runtime was a single import; tree-shaking couldn't remove unused directives or pipes because the
.ngfactoryfiles referenced them all eagerly. - Compilation model. The factory files were a parallel source tree. Editor tooling had to know about them, debugger source maps had to map back through them, and they grew faster than the source tree.
- Generic components. Generic types didn't survive into the factory; component generic parameters defaulted to
any. - Locality of compilation. A single component's compile depended on knowing every directive in scope, which meant the compiler had to read the whole
NgModulegraph to compile any one file.
What Ivy is
Ivy is instruction-based. Instead of a .ngfactory.ts file, the compiler emits Ivy "definitions" directly onto the decorated class as static fields:
Component.ɵcmp = ɵɵdefineComponent({...})— aComponentDefcontaining a template function and metadata.Component.ɵfac = (...) => new Component(...)— the factory.Directive.ɵdir,Pipe.ɵpipe— analogous for directives and pipes.
The template function calls runtime instructions imported by name (ɵɵelementStart, ɵɵproperty, etc.). Bundlers tree-shake unused instructions out of the build.
Implications still felt
A lot of today's behavior is best explained as "this is how Ivy works":
- Generic components.
R3Component<T>flows through the compile pipeline; the type parameter is preserved in the emit and visible in templates viastrictTemplates. - No more
.ngfactory.tsfiles. The compile is a TypeScript transform; the output is.jsfiles at the same paths as the source. - Tree-shakable instructions. Adding a new template feature usually means adding new instructions, not enlarging the runtime surface for everyone.
- Local compilation. Ivy's compile model is per-class. The compiler still reads the module graph for scope resolution, but each class's emit doesn't depend on the others'.
- The
ɵprefix. Public-internal APIs that the compiler emits names for are prefixedɵto make their privacy obvious. Don't import them. - Instruction calls in stack traces.
ɵɵelementStart,ɵɵproperty, etc. show up in profiler traces and stack traces; if you see one in a bug report, you're looking at compiled template code. - Partial compilation. Libraries can ship a stable intermediate IR and let consumers' bundlers finish the compile via the linker, decoupling library publishing from framework releases.
The migration cost
Migrating from VE to Ivy was framework-internal — application code mostly didn't notice. The places that did notice:
- Library authors. Pre-Ivy libraries had to either republish in Ivy form or rely on the linker to upgrade them at install time.
- Testing harnesses.
TestBedhad to learn the new compilation contract. - Custom decorators /
ng-packagr. Tools that introspected the framework's compilation output had to learn the new emit format. - Generic constraints. Code that had silently relied on generics being erased into
anystarted getting type errors.
Most of these settled within the v9–v11 window. The final VE removal happened in v13.
The runtime side
Ivy's runtime (packages/core/src/render3/) is the deepest, most performance-critical code in the framework. The LView/TView data structures are designed for monomorphic V8 access; the instruction set is designed for tree-shaking; the change-detection model is designed for incremental walks. The trade-off is a steeper learning curve — the code reads like an interpreter, because it is one.
The internal design notes left over from the bring-up are still useful reading:
packages/core/src/render3/PERF_NOTES.mdpackages/core/src/render3/VIEW_DATA.mdpackages/core/src/render3/CODE_GEN_API.mdpackages/core/src/render3/TREE_SHAKING.md
Why "Ivy"?
The name predates published documentation; the plant connotation is informal. Internally the codebase still uses "Render3" (render3/) interchangeably — the package paths haven't been renamed. New contributors should treat Ivy, Render3, and the runtime as synonyms in source-code commentary.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.