All you need to know about Ivy, The new Angular engine!

Smaller bundles, faster compilations, Better debugging, dynamic loading of module and components and advanced concepts like Higher order components. Angular Ivy — The complete guide for the 3rd generation of the Angular renderer.

Eliran Eliassy
Angular In Depth
7 min readJun 10, 2019

--

AngularInDepth is moving away from Medium. More recent articles are hosted on the new platform inDepth.dev. Thanks for being part of indepth movement!

Over a year ago, the Angular core team announced on ng-conf that they are working on Angular Ivy, and even though it’s not 100% ready for production, I’m feeling like this is a really good time to dive deeper into the new renderer of Angular.

After a long wait, Angular version 8 is here!

This is a major release bringing a lot of cool (and important) features as Differential Loading, New builder API, Web-Workers support and more.

But above all those, Ivy is finally opting-in!

Why Ivy?

First and foremost — Mobile devices!

It might sound insane but 63% of all US online traffic comes from smartphones and tablets. By the end of this year, 80% of internet usage is expected to come from mobile devices. (Source)

One of our biggest challenges as front end developers is to load our website as fast as we can. Mobile devices unfortunately often suffer from a bad or slow internet connection and making this challenge even harder.

On the other hand, we can use many solutions to load our application much faster e.g: use CDN to serve the files from the closest cloud, PWA to cache the assets and many others. But the biggest opportunity we have as developers is Reducing the bundle size.

Reducing the Bundle size

So…bundle size. Let’s see it in action. Let’s take eliassy.dev as a case study. This is a simple web site build with Angular it looks simple but it uses a lot of core features. It also uses the Angular PWA package to support offline and Angular Material with the Animation Module.

eliassy.dev working on offline mode

Before Ivy, my main bundle weight was a bit more than 500 kb.

eliassy.dev main build before Ivy

Now let’s opt-in Ivy by editing the tsconfig.app.json and add a section of angularComplierOptionand set the enableIvyto true. for new Angular CLI projects, you can just use the --enableIvy flag when running your ng newscript.

Now let’s build the app again using ng build --prod:

eliassy.dev main build after Ivy

We can see that our bundle shrunk in 77KB which is 15% of the bundle size, that means our website’s loading time will be 15% faster.

Some of you might be disappointed by the fact we cut only 15% of the bundle size. The reason for this is even though this is a small project it’s still relying on a lot of core features and for now, Ivy is mainly cutting the generated code and not the framework itself.

Stephen Fluin just posted that the core team is still working on making the bundle size even more smaller:

“We are now working on reducing the framework size so that we have reduced bundle sizes for real applications in nearly every case before making Ivy the default. Additional benefits will also be possible as we offer new ways of bootstrapping that will leave out more of Angular from your main bundle.”

How does it work?

So, what’s behind it? How does it work?
To understand that we need to go to a deep dive inside the internals of the compiler. Let’s create this simple code:

Now, let’s run the ngccommand to generate the transpiled code:

  1. For the view-engine renderer: node_modules/.bin/ngc

2. For Ivy: node_modules/.bin/ngc -p tsconfig.app.json

It’s changed a lot, but a few main differences are important here:

  1. We don’t have factory files anymore, now all the decorators converted into static functions. In our example the @Component converts into a ngComponentDeffor example.
  2. The set of instructions has changed so it can be tree shakable and will be much smaller.

Not only smaller bundles

If we take a look at the ngIfsection of the transpiled code:

For some reason, my app component is associated with ViewContainerRefand TemplateRef. If you wonder where those 2 came from, they are actually dependencies of the NgIf directive implementation.

In Ivy that becomes much more simpler, every component now references child components or directives though much more cleaner public API. The meaning is when we change something, e.g: the implementation of our NgIf, we won’t need to recompile everything, we can just recompile the NgIfand not the AppComponent class.

This way we had achieved not only smaller bundles, but also faster compilations, and easier way to ship libraries to NPM.

Debugging with Ivy

Ivy is providing also much easier debug API.

Let’s create an input with a (input)event and bind it to a not exist function named search:

Before Ivy, When trying to type something inside the input, we get this in the console:

With Ivy our console will look much more informative about where we got the error from:

So we earned another goal with Ivy, better template debugging!

Dynamic loading

We have a simple app, with 2 modules, app module, and feature module. The feature module will load lazily with the router and will display the feature component. So, When I’m clicking on the click me button, I’m getting the feature module chunk in the network:

Angular 8 brings a new API for loading modules, it now supports ES6 dynamic import.

Before:

And after:

With that given, why not try the same exact import directly on the component?

And the result:

It’s actually working!! but wait… Something weird just happened. We have loaded a component, without declaring it in the module.
So, should we still declare components in modules? Or, are modules optional now? We will answer that soon, but first, let’s try to add this component to the view.

For this purpose let’s use the `ɵrenderComponent` function:

I’m getting an exception here which make sense cause we trying to attach the component to the view, but didn’t tell who is the host element right?

Here we have 2 options, the first one — is to add the FeatureComponent selector to the DOM, and Angular will know to use render the component on the selector placeholder:

Or renderComponent has another signature getting a config where we can set up the host. We can even add a not existing host, and Ivy will attach it to it:

Are Modules still necessary?

As we just witnessed, we don’t need to declare a component on the module. It makes all of us wonder if we really need Modules?
To answer this, let’s create another use case on- Now FeatureComponent will inject a config that will be declared and provided in the AppModule:

FeatureComponent:

Now — If we try to load the component again, we get an exception cause our component doesn’t have an injector:

There are also downsides for not declaring component on the modules, we actually not getting them with injectors. Despite this,renderComponent config also letting us declare an Injector:

And the result:

Yay! It works!

Higher Order Components (HOC)

As we just saw — Angular is now much more dynamic, And it also allows us to implement advanced concepts like HOC.

What is HOC?

HOC is a function which gets a component and returns a component but also affecting the component in between.

Let’s create the basic HOC by adding it as a decorator to our AppComponent:

Now let’s leverage the concept of HOC and dynamic import to create a lazy component:

Few interesting points to talk about:

  1. How to get the injector without the Angular DI? Remember the ngc command? I’ve used it to check how Angular translating the constructor injection inside the transpiled files and found the directiveInject function:

2. I’ve used the HOC function to create a new “life cycle” function named afterViewLoad that if it exists on the original component, it will be invoked after the lazy component got rendered

The result (Directly on load):

Summary

Quick summary on what we just learned:

  1. Ivy, the 3rd generation of Angular compiler is really here! It has a backward compatible and by using it we can get smaller bundles, easier to debug API, faster compilation and dynamic loading of modules and components.
  2. The future of Angular with Ivy looks exciting with cool and exciting features like HOC.
  3. Ivy also sets the ground for Angular Elements to become much more popular in our Angular applications.
  4. Give it a TRY! It’s just as simple as setting the enableIvy flag to true!

Thanks for reading!

Ivy is coming on stage

You can check out my talk on AngularUP 2019 conference about Angular Ivy:

Visit my website for more content.
Contact me on Twitter.
Special thanks for reviewing: Itay Oded & Uri Shaked.

--

--

Eliran Eliassy
Angular In Depth

Google Developer Expert in Angular & Web Technologies. Founder and CEO @ e-square.io. Angular enthusiast, Public speaker, Community leader.