What the hell is Zone.js and why is it in my Angular 2?

Note: If you’re interested in a brief overview of zonejs and what it does, stay here. If you’re looking for a deeper dive, check out my series on how Angular2 works on a source code level here: https://medium.com/@MertzAlertz/a-deep-dive-into-angular2-part-1-application-refs-b15d62a86246#.bbksupdvq

I’ve been playing around with the Angular 2 beta, and ran across the list of required packages to make angular work. So, if took a gander at the old readme for Angular 2 in the bundles folder, and it mentions a few things you need to include;

Polyfills are required for Angular 2 to function properly (the exact list depends on the browser used) and external dependencies ([zone.js](https://github.com/angular/zone.js)).

Wat. What is this Zone.js thing, and why do I need it? This is bullshit, my personal space is being invaded and I don’t like it.

A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs.

Oh, that’s pretty nifty, so my stack traces won’t suck as much? Neato, thanks Angular dudes! So Angular probably just uses this for errors, stack traces, etc., kind of like domains in nodejs?

Not so much… It turns out there’s a bit more slapped onto these zones.

Let’s do an experiment. Go and take your favorite Angular 2 app, and don’t include zone.js. See what happens, I’ll wait here. Notice anything interesting? None of the bindings are working!

Take a look at some of the code. The Application subscribes to zone’s onTurnDone event, which, if we do some more digging, calls tick, which actually calls all of the change detectors. So, without zones, we don’t get any change detection, so we don’t get any of the nice UI updates that we’d expect!

Note: It’s here that I should say that zones are not required for change detection in general, they simply are the means by which Angular picks up changes and then calls tick so that any listeners for those changes are actually fired. Thanks Maxim Koretskyi!

Why does any of this matter? Well, in Angular 2, we don’t have a $digest like in the original angular, so if we were to do something like this in Angular 2:

let marker = new google.maps.Marker({
position: new google.maps.LatLng(1, 1),
map: someMap,
title: 'Title of a marker'
});
marker.addListener('click', () => {
this.someProperty = Math.random();
});

Then the UI wouldn’t actually update properly, because someProperty actually is updated outside of Angular’s zone. So we have to include something like this in order to get the correct updates:

marker.addListener('click', () => {
this.zone.run(() => {
this.someProperty = Math.random();
});
});

In other words, zone.run() is kind of like the new $digest().