Pete Mertz

@MertzAlertz

How does Angular2 work? Part 1 — Application Refs

Forward

I’m an Angular 1.x developer. I work in Angular 1.x every day and would say I know my way around a digest cycle. I took a very learn as you go approach to Angular 1.x, and with Angular 2 I’m going to be a little more pragmatic.

I’m going to attempt to pick apart and document each step and section that an Angular 2 app goes through in order to go from javascript to DOM elements on the screen.

Setup

A little background for where my app, lovingly referred to as “client,” is starting from. I installed the angular-cli package and simply called

> ng init

Pretty complicated setup there, actually I really like this for starter apps. Compared to a long and arduous manual setup, it’s a very nice way to get started fast.

Now, most of the compilation/packing steps are wrapped up in a blackbox webpack system included with angular-cli, so we’ll start with src/main.ts.

main.ts imports some polyfills and basic stuff that the typescript compiler and angular will need to run properly in the browser.

Now let’s get into some actual meat.

And so it begins… it’s turtles all the way down.

platformBrowserDynamic().bootstrapModule(AppModule);

What in the world does this mean? Let’s dig, first we go here, this is the declaration for platformBrowserDynamic. In it, we find that we see

export const platformBrowserDynamic = createPlatformFactory(        
platformCoreDynamic,
'browserDynamic',
INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS
);

Now we’ve established that there’s something called a Platform (as well as a platform factory.) Following this call, we’re redirected to a file called application_ref.ts. We see that the argument names, in order, are

  • parentPlaformFactory: (extraProviders?: Provider[]) => PlatformRef
  • name: string
  • providers: Provider[] = []

The names seem pretty self explanatory. The first thing to note is the INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS. You can find all the things that provides here, or if you just want me to tell you, it’s all of the modules necessary for doing browser specific rendering. This is basically the platform specific part of these calls. Everything else is, well, Core.

Let’s dig into the first argument, “parentPlatformFactory”. In the case of the starter app, we can see that this is platformCoreDynamic which we get from the compiler module. What lies here you may ask? More platform factories! It’s turtles all the way down.

export const platformCoreDynamic = createPlatformFactory(
platformCore,
'coreDynamic',
[{
provide: COMPILER_OPTIONS,
useValue: {},
multi: true
}, {
provide: CompilerFactory,
useClass: RuntimeCompilerFactory
}, {
provide: PLATFORM_INITIALIZER,
useValue: _initReflector,
multi: true
}]);

So now we have another platform based off of something called “platformCore,” which we’ll dig further into in a second. Note that it looks as though we’re providing a lot of compiler related modules. These are related to taking the angular code and templates and compiling them into render-able components. Most notable here is that the RuntimeCompilerFactory is supplied as the CompilerFactory. This means that we’re doing JIT compilation, as opposed to compiling the angular app ahead of time.

platformCore. What are you? Let’s find out. It comes from angular/core, and we find…

export const platformCore = createPlatformFactory(
null,
'core',
_CORE_PLATFORM_PROVIDERS
);

We have reached the end though, the granddaddy platformFactory. ‘core.’ It even has a great name, it is the core. the last. the center. If you look into what the _CORE_PLATFORM_PROVIDERS are, they look to be a bunch of pretty general stuff, reflector, console, generally providers that provide basic functionality for any app.

Great, let’s unwind, all the way back up to our original call to createPlatformFactory to figure out what all this means. The first line of createPlatformFactory looks like this;

const marker = new OpaqueToken(`Platform: ${name}`);

OpaqueToken is just a container for the name, basically Angular2’s version of a Symbol. So far so good.

return (extraProviders: Provider[] = []) => {    
if (!getPlatform()) {
if (parentPlaformFactory) {
parentPlaformFactory(
providers.concat(extraProviders).concat({
provide: marker, useValue: true
}));
} else {
createPlatform(ReflectiveInjector.resolveAndCreate(
providers.concat(extraProviders).concat({
provide: marker, useValue: true
})));
}
}
  return assertPlatform(marker);  
};

The first statement, getPlatform(), checks to see if createPlatform() has ever been called, i.e. if there is an assigned platform. The first time we call createPlatform (way back in core), we create a platform according to the created injector. Let’s take a look at that file again. As we can see, PlatformRef has been assigned to PlatformRef_ from the application_ref file. Back over there, we see that it’s an implementation of the abstract class PlatformRef.

The Angular platform is the entry point for Angular on a web page. Each page has exactly one platform, and services (such as reflection) which are common to every Angular application running on the page are bound in its scope. * * A page’s platform is initialized implicitly when {@link bootstrap}() is called, or * explicitly by calling {@link createPlatform}().

So, we’ve finally made it to our Angular application. In the next part we’ll investigate what actually happens when you call bootstrapModule.

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising &sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!

More by Pete Mertz

Topics of interest

More Related Stories