${post.fImageName}

Angular myths busted

Whether you are into web development or not, you probably have heard some rumors about Angular JS. Let’s go through most common of them and see if they are true.

Never heard of it before

Ok, first things first. The basic building block of Angular application is component. This is a plain class annotated with some metadata making it an Angular component. Here’s an example from angular documentation:

Typical angular component class

Components must at least define a template (or templateUrl), that is HTML that tells Angular how to render the component, and a selector, which is html tag name used to specify component in templates.

In case you don’t need a template, there are directives. Directives are components without a template and they use @Directive decorator. Directives can be structural and attribute. Structural directives alter layout by adding, removing, and replacing elements in DOM. Attribute directives alter the appearance or behavior of an existing element.

To organise components into logical cohesive blocks Angular uses modules. Just like a component or directive, an Angular module is a class with a decorator. This time it’s @NgModule. 

Typical angular module

Angular supports data binding, a mechanism for coordinating parts of a template with parts of a component. Values can be passed from component to template (interpolation and property binding), from template to component (event binding) and both ways (two-way binding).

In order to fetch data there are special entities called services. But they are not limited to fetching data. As stated in angular documentation:

Almost anything can be a service. A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well.

And what is really peculiar about services, is that Angular takes care of creating and ensuring there is only 1 service instance present as well as injecting them into components using dependency injection mechanism.

What it actually means is when creating a component Angular looks at the types of constructor arguments and tries to supply it with needed object. For example having saw this in a component class: 

Dependency injection in constructor

Angular will try to find service by type Logger, that was declared in module providers earlier: 

Class that is injected

This approach not only makes code more readable, it also makes components and services loosely coupled making testing much easier.

Is it Angular JS, or just Angular, or Angular 2...wait, 4 ?

The short answer is - just Angular.

The world first knew it as Angular JS, which was the name of the first version of framework. Starting from version 2 it is called just Angular. Why not Angular 2 ? Because starting from that version Angular team adopted semantic versioning and fixed release schedule.

Semantic versioning

It says to release:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.

Release schedule

It was decided to do:

  • patch releases every week,
  • 3 monthly minor release after each major release and
  • a major release with easy-to-migrate-over breaking changes every 6 months.

What that means is, in order to ease migration, there will be new major version twice a year. That means that version number will increase pretty fast and to avoid confusion, it is not mentioned in the title.

Okay, there’s version 4 already, where’s version 3 then ? No number magic here – that’s because of the router package. It was version 3 while all the other packages were version 2, so version 3 was skipped to align package versions.

I used Angular JS and I didn’t like it

And Angular 2 is the same old Angular JS, with all its problems, but packed with fancy new features, right ? Wrong ! Angular 2 was re-written from the ground up, with new APIs and new patterns. Just take a glimpse at the size of upgrade to Angular 2 guide to get the idea of how much have been changed !

Main differences with version 1 are:

  1. Angular 2 is written in Typescript
  2. Say farewell to $scope and controllers, Angular 2 uses components
  3. It uses modules to organize components
  4. Makes heavy use of dependency injection, what makes testing a breeze
  5. No more $digest, zone.js is used to detect changes (more here )
  6. Uses observables instead of promises (more here)

Why do I need another Hypescript ?

Typescript. It’s typescript ! And it is an open source superset of javascript developed by Microsoft. But being written in Typescript Angular 2 doesn’t limit you to it. Apart from it you can use Dart and of course vanilla JS to write your precious code.

Let’s look at the typical typescript class: 

Inheritance in typescript

That gets compiled to the following javascript: 

The above example compiled to javascript

Looks much neater in Typescript, huh ?

But it’s not only about beauty ! Typescript adds static typing, classes, interfaces, inheritance, annotations and generics to javascript. Meaning not only it helps spotting common errors as you type the code with better IDE suggestions, but also makes type checks during compilation preventing incorrect usages or assignments. It also allows plenty room for application scaling and makes refactoring safer.

And if you are wondering about debugging compiled javascript, all modern browsers and IDEs support direct debugging of typescript files through sourcemaps, that are produced during compilation.

I don’t want to configure anything, I just want to code

Good news, everyone! Angular command line interface has been officially released and this is exactly where you should start. Not only it will configure everything for you, it will even help you to move faster and more error proof with code linting and generation.

First, make sure that you your node.js version is at least 6.9 and npm version is 3.3 and up.

Then, install angular-cli globally with the following command

Installing angular-cli globally

Now you can use angular-cli. Let’s generate a skeleton app by running

Generating new angular project

This will produce a lot of files inside my-app folder. Among them are typescript compiler configuration, karma test runner configuration, protractor e2e tests configuration, tslint linter configuration, it’s very own angular-cli configuration file, app module and a sample component file. Full list of generated files and their description is available here.

To see the app in action, navigate to project folder and type following command 

Starting angular application

And voila! Your first angular application is available at localhost:4200

But that is just a tiny bit of angular-cli possibilities. Other commands include:

  • Generation of application skeleton
  • Generation of components, modules, directives, services, guards, pipes and virtually every angular entity and adding it to module declaration
  • Running e2e and unit tests
  • Linting source files
  • Setting / getting configuration values
  • Extracting i18n messages from source code
  • Building the application
  • Ejecting your application and outputting the proper webpack configuration and scripts.

Full list of available commands is always available by typing

Type this in case of emergency

It’s enormously huge

Well, hello world application generated by angular-cli loads 2610 KB when you open it in browser just to show you that “App works!”. 2423 KB of that is Angular framework alone. It may be negligible small comparing to the size of the universe, but it is pretty hefty in terms of web development. Let’s find out if it can do better!

Angular-cli has 2 environments configured: development and production. By default all angular-cli commands use development environment. But we can switch them as we please, so let’s try building the app for production. 

Serving for production

Which is alias for 

Serving for production the hard way

Believe it or not, total page payload dropped to 135 KB with angular sources taking just 111KB, which is 20 times smaller than it was before ! What happened under the hood was 2 things: tree-shaking and uglifying.

Tree-shaking

Tree shaking is a term commonly used in the JavaScript context for dead-code elimination, or more precisely, live-code import. Basically it follows every import and export statement and checks that it is used. Note that it will not remove the code from the generated bundle, but rather mark it as unused and avoid adding exports for such code.

Uglifying

It is applying uglifying after tree-shaking, what brings most noticeable changes. Along with mangling and minifying the code, it removes unused entries from the output, reducing the overall size of the bundle.

It takes a lifetime for the app to load

Ok, we have seen how to speed up page load by reducing Angular bundles size, but what if it’s Angular’s javascript execution what takes so much time ? It turns out we can boost it as well and here’s how.

An Angular application consists largely of components and their HTML templates. Before the browser can render the application, templates must be compiled by Angular compiler.

By default angular compiles the app at runtime in the browser using the just-in-time (JIT) approach.

JIT compilation

Views take longer to render because of the in-browser compilation step. The application is bigger because it includes the Angular compiler and a lot of library code that the application won't actually need. Template compilation errors are discovered only at runtime.

Alternatively one can use ahead-of-time (AOT) compilation.

AOT compilation

With AOT, the browser downloads and renders pre-compiled version of the application, without waiting to compile the app first. According to angular documentation the compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload. Due to template compilation made during build, errors are discovered early.

There’s also server side rendering, which is a variant of aot compilation that renders the page completely on server but we’ll cover that later.

Lazy loading

Although not particularly useful for this hello world application, bigger apps can further benefit from adopting lazy module loading.

Thanks to Angular modules we are able to group related pieces of functionality of our application and load those pieces on demand, saving precious load time. With lazy loading only the bare minimum needed to display the page is loaded initially. Lazily loaded modules are not loaded unless user navigates to their routes.

It’s not progressive web app compatible

You may have heard that angular-cli used to have --mobile flag while in beta, that was responsible for generating some PWA features. Well, it was decided to drop it for now after migrating to webpack build system.

But that doesn’t mean that Angular apps cease to be progressive ! All it means is angular-cli is not generating PWA features (namely service worker and manifest file) any more and this is to be done by you now.

This is easily done by using Google’s SW Precache library for example. It’s a build time tool that looks through static resources (JS, CSS and HTML) and generates a service worker file for you.

We have a series of articles about PWA in case you want to dive deeper.

It’s not search engines friendly

Single page applications, like the ones written with Angular, are great. They handle all user interaction on the client, maintain application state and eliminate the need of page reloads, but there’s one hickup - search engines don’t see content of your application.

Search engine crawlers expect plain html and not all of them are able to wait until your app has started. Thus, they usually ‘see’ something like this: 

Your app through the crawler's eyes

Not exactly what we would like them to see, eh ? Same thing happens when user tries to share a page with SPA.

But what if we could supply them with a pre-rendered page ? And this is exactly what server-side rendering does.

Server-side rendering

In essence it manages the state of the app on server to be able to render the page upon request, same as it would’ve been done on the client.

Server-side rendering for Angular is called Universal. Angular Universal works by compiling the app to make it capable of running on the server, a form of ahead-of-time compilation. And most importantly it brings us following features:

  • Makes application SEO friendly by rendering page on the server and serving it as string, completely eliminating the need of client-side compilation.
  • Further reduces starup time (even compared to AOT). And the slower is the network, the bigger is advantage of having page pre-rendered by Universal.
  • Makes application more PWA friendly by gracefully degrading to server-generated application on slow connections and/or incompatible browsers.

NOTE: The resulting Universal app does not handle browser events such as mouse or keyboard inputs, nor send AJAX requests!

But don’t worry -- Angular app is still going to be loaded and there’s a tool called Preboot that will record browser events until full Angular app is loaded and play them back.

It doesn’t use shadow dom

No, it does not use it by default, to correctly work in all browsers. But that can be changed by specifying encapsulation property on the component decorator (more here). Possible variants are:

  • ViewEncapsulation.None - No Shadow DOM and style encapsulation.
  • ViewEncapsulation.Emulated - No Shadow DOM but style encapsulation emulation (default value).
  • ViewEncapsulation.Native - Native Shadow DOM.

Data binding slows my app

For the data binding to work Angular uses change detection. Let’s see how it works.

Change detection

Every Angular component gets a change detector responsible for checking the bindings defined in its template. It can perform hundreds of thousands of checks within a couple of milliseconds. This is mainly due to the fact that Angular generates VM friendly code and contrary to Angular 1, change detection graph is a directed tree and cannot have cycles (more here).

Angular has to check every component every single time an event occurred because javascript gives no object mutation guarantees. But we can further reduce the amount of these checks by telling Angular what components have changed with help of immutables and observables.

Immutables

Using immutables means that we cannot change object property without creating new object, so whenever there’s a change, we get a new reference.

Let’s assume we have created an immutable object 

Creating an immutable object

Now changing any Billy’s property will result in a new object, so we can tell Angular to skip Billy’s properties change detection and do it only when it sees a new object reference with ChangeDetectionStrategy.OnPush: 

Making use of immutables to reduce change detection checks

And this way we can skip entire component subtrees checking !

Observables

Unlike immutable objects, they don’t give new references when a change is made, but fire events that we can subscribe to.

Ok, so we set the ChangeDetectionStrategy.OnPush again, but the reference to the observable property is never going to change, so how do we let Angular know that the change has happened ?

We make use of ChangeDetectorRef class, to mark this component as changed. This is a reference to angular’s change detector attached to every component. 

Making use of observables to reduce change detection checks

Now component is marked for change detection after person was changed only.

Conclusion

At the end of the day Angular is not so black as it is painted !

It is packed with loads of features and can be pretty lightweight, fast, progressive and SEO-friendly !

Yes, it can be used right out of the box without any previous experience, but, as it is with every complex framework, to be able to exploit its full potential and use it effectively I recommend spending some time to understand its principles and common techniques.

Of course there are shortcomings, but they are no real deal-breakers and Angular team works tirelessly on making it better. One of such things is documentation, that could be a little more thorough, but there is huge community around it that is a great help in development.

Based on my experience I would advise to:

Get it

  • To have server-side rendering because of Universal
  • To use Test-driven development (TDD) or simply to have 100% test coverage because Angular is made with testing in mind
  • To have static typing and ES6 features (like classes, generics, inheritance) because it has full Typescript support
  • To make a medium-to-large application that is possibly going to expand because it has modular architecture, lazy loading and dependency injection
  • To keep your dependencies down to one framework instead of having multiple third-party libraries

Forget it

  • If you don’t need a Single-page application (SPA) or need a simple one without features like routing, data-binding and dependency injection
  • If your team is familiar with other framework, and time is of the essence

Read more

  • Angular documentation
  • Angular CLI documentation
  • Webpack bundler documentation
  • Universal server-side rendering
  • Thoughtram - a blog by Angular contributor Pascal Precht with massive collection of in-depth articles
  • Rangle.io - has an online version of the Angular 2 book, covering all aspects of the framework
  • Nrwl blog - a blog by Angular team members and former Googlers Jeff Cross and Victor Savkin

Thanks !

Feel free to contact me at pmi@enonic.com if you have any questions or suggestions regarding this article, the Life, the Universe, and Everything.