๐ Closures in Angular: The Backbone of Ivy, View Engine, and Micro Frontends


Let's deep dive into Angular's internals, focusing on View Engine, Ivy, and Micro Frontends.
1๏ธโฃ View Engine vs Ivy (How Angular Uses Closures Internally)
Angular originally used View Engine, which was replaced by Ivy in Angular 9. Let's compare their internals and how closures play a role.
๐ View Engine: Pre-Ivy Angular Compilation (Before Angular 9)
View Engine converted Angular templates into JavaScript functions.
Each component had a factory function that was invoked to generate the view and bindings.
These factory functions relied on closures to encapsulate component metadata.
๐น Example: View Engine Generated Code (Pre-Ivy)
A simple template:
<h1>{{ title }}</h1>
was compiled into:
function View_AppComponent_0(ctx) {
return [
// Closure stores the component instance (ctx)
new TextNode(ctx.title)
];
}
๐ How Closures Worked in View Engine:
The function
View_AppComponent_0
stores the component context (ctx
) inside a closure.If
title
changes, the closure updates the TextNode.
๐ด Problems with View Engine
Large Bundle Size: Each component had its own factory functions, leading to bloated output.
Heavy Memory Usage: Closures were created for each component factory, causing unnecessary memory overhead.
Slow Compilation: Every component was pre-compiled, making builds slow.
โ Ivy: The Modern Angular Compiler (Since Angular 9)
Ivy replaced View Engine, introducing: โ
Tree-Shaking for Unused Code
โ
More Efficient Closures
โ
Runtime Compilation Instead of Precompilation
๐ Ivyโs Closure-Based Rendering
Now, instead of factory functions, Ivy uses instructions (functions that act as runtime closures).
๐น Example: Ivy Generated Code
function Template(rf, ctx) {
if (rf & 1) {
text(0, ctx.title); // Uses closures at runtime
}
}
๐ How Ivy Uses Closures More Efficiently
Instead of creating separate factory functions, Ivy keeps templates as functions.
This means only components used at runtime are compiled, reducing bundle size.
2๏ธโฃ Micro Frontends in Angular (Module Federation and Closures)
Micro Frontends (MFEs) allow independent teams to build Angular apps separately and integrate them dynamically.
๐ How Closures Play a Role in Micro Frontends
Encapsulation: Each Angular app loads inside an isolated closure, preventing conflicts.
Lazy Loading: Remote modules are loaded on demand, using closures to manage instances.
Runtime Sharing: Closures hold shared dependencies (e.g., Angular, RxJS), reducing duplicate code.
โ Example: Micro Frontend with Module Federation
In webpack.config.js
, we use:
new ModuleFederationPlugin({
name: "shell",
remotes: {
mfe1: "mfe1@http://localhost:4201/remoteEntry.js",
},
shared: ["@angular/core", "@angular/common"]
});
๐ How Closures Are Used
Each MFE is wrapped in a closure.
The shell application calls these closures only when needed.
๐ Key Takeaways
โ
View Engine used closures inefficiently, causing performance issues.
โ
Ivy uses closures dynamically at runtime, improving bundle size & speed.
โ
Micro Frontends use closures for isolated execution and dependency sharing.
Subscribe to my newsletter
Read articles from Rohit Bhat directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
