At Grio, we love Angular. By my estimation we currently use it for at least half of our front-end web application code. And I in particular have affection for it, so I greeted the recent release of Angular2 with some interest and trepidation.
The release was just an event, though. The framework had already been around long enough for me to fret about it for some time.
Angular 2.0 was announced at the ng-Europe conference in September of 2014, nearly two years to the day before its release. It has been in continual flux for much of that time. For a long period, just to take the most dramatic example, the language of choice was Google’s own AtScript which is a superset of the currently favored TypeScript. At some point that plan just vanished and we descended one rung on the language ladder. When I started this article the version was RC5 (of 7) and the routing module was still considered fundamentally malleable.
All that’s changed. Everything is now rock-solid… I can only assume. Now is the time to take this framework out for a spin.
Before, even those of us who wanted to wade into the morass of ever-changing specifications found the barrier to entry relatively high, what with typescript and other configurations necessary to just get off the ground. Even ready-made seed projects tended to be out-of-date. Personally, I made a couple of forays into setting up a project and went away discouraged when I found that it was going to take substantially more than the 15 free minutes I had on hand.
That isn’t true any more with Angular-CLI ( https://cli.angular.io/ ) it appropriates a number of features from other tools (code generator, build system, development server) and combines them in an angular2-specific package. It’s dead-easy to set up a new project:
and because it’s produced in concert with the angular team itself it generates code in line with the fledgeling best-practices of the community.
Will it replace a build tool? Not at the moment. Not for a production project. But then, I can’t imagine that it aims to do so.
So now that we have a project set up, we can take a look at the framework itself. It retains many of the concepts and terms from Angular 1, but they are expressed entirely differently. It is, for those who didn’t already know, a completely different codebase from Angular 1, built from the ground up.
Typescript
Let’s talk about TypeScript for a moment. Well… not about TypeScript per se because I don’t actually know very much about it. Let’s talk about the idea of TypeScript and the decision to use it as the de facto language of Angular 2. Oh sure, you can supposedly use javascript, but only a quick start is available in the documentation. Or how about Dart? That’s also available. Any takers?
Like it or not, most Angular2 apps will be written in Typescript. I don’t yet feel sold. ECMAScript2015, while still requiring a transpiler, at least holds the promise that it will someday be run in-browser. Typescript will always need a transpilation step, and source maps. It also requires that you maintain a tsconfig file and typings files for imported javascript libraries, and thus can add a bit of complexity to your codebase.
On the upside, by adding type-checking, Typescript can substantially improve the quality of the resultant javascript code.
To some extent it comes down once again to the initial learning curve. Typescript isn’t particularly difficult or confusing; it’s mostly familiar, being a superset of javascript with features of other common languages, but it is a new language nonetheless, and some aspects of it, like decorators, are central to Angular2.
In the end, Angular2, assuming it takes, will make Typescript more of a standard and less of an outlier.
Performance
Over the last few years complaints have been emerging more and more rapidly about Angular 1’s sluggish performance when rendering the DOM. Angular2 takes this performance issue seriously. It replaces the digest cycle with a change detection algorithm that walks the DOM tree. The results are dramatic.
These are just a couple of the areas where Angular2 outperforms its predecessor, usually by a similarly vast margin.
Components
Angular2 focuses on components — a large portion of one’s time as a developer will be spent writing components. These derive from the web components standard, such as it is. Components replace both the controller of Angular 1 and the element-based directive. In essence a component is the code that is married to a view/template, although conceptually the view lies under the component’s umbrella as well.
Writing a component is easy enough. It’s just a Typescript class decorated with the @Component() decorator, which will include a few properties.
@Component({selector: 'my-app',
template: '<h1>My First Angular App</h1>'
})
class AppComponent { }
Anywhere the tag <my-app></my-app> is found within the enclosing document (or specified scope thereof) it will be replaced with the compiled template string. Functionally it closely resembles the directives I’ve been writing for a while now, but it’s expressed much more clearly and appropriately.
Templates
However, along with the component model comes a templating syntax that is — if I may — absolutely nutso. I am perhaps biased here. I thought the way that Angular 1 bindings were done (despite being occasionally muddy in its intent) fit seamlessly into standard HTML as though it belonged there. By contrast, Angular2 template elements have all the grace of ColdFusion circa 1999.
The double-brace interpolated bindings remain
{{person.name}}
but now we distinguish property bindings
[value]=“person.name”
event bindings
(click)=“doAction()"
two-way bindings
[(ngModel)]=“person.name"
and structural directives
*ngFor=“person in people"
each identified by its own set of delimiting characters.
We also have a new feature, template reference variables
#person
I, for one don’t get a thrill from this punctuation mania. I only hope that it contributes to the previously mentioned performance gains, or that it offers some other, hidden gain which will be revealed at a later date. I realize that “it looks dumb” isn’t really a legitimate critique, but if it were, Angular2 would already be out on the scrap heap.
Services and Dependency Injection
Services are now a simpler matter than in Angular 1. They are simply classes, decorated with the @Injectable() decorator. To put it another way, any injectable class is a service. The process of injection is as follows:
1) Decorate the service class with @Injectable(), like so:
@Injectable()
class InjectableService {
}
2) Insert the service in the module’s providers property (covered in the next section)
providers: [InjectableService]
3) Accept the service as a constructor argument of the class into which you want the service injected:
constructor(injectableService:InjectableService)
There’s more to it, and there are many options, but this is the basic approach to DI. Its complexity is equivalent to Angular1’s with regard to amount of code affected: changes need to be made to service class, module definition and injection point. One of the changes in Angular2 is that the service is not inherently tied to an angular module; there’s no code like:
angular.module(“app”).service(“InjectableService”,… etc.
This has advantages and disadvantages. It allows the developer to pick and choose services to include in a given module. It also forces the developer to do just that, rather than bundling everything in a module. However, if you’re following the pattern that I’ve seen in a number of projects — each service is given its own module — that difference is effectively irrelevant.
Modules
Modules continue to be a significant structural element of Angular2. The main module is the entry point for bootstrapping the application. Modules have four significant arrays: imports, exports, declarations, and providers. Declarations represents the features — components, directives, etc. — you plan to use internally. Imports represents other modules whose features you plan to use. Exports are the features you want to expose to other modules. And providers are the service providers you want to inject into the components, etc. of this module. In a sense, modules are now less simply a bucket for containing related items and more of a structural element, organizing and controlling the flow of information.
Conclusion
At first glance Angular 2 seemed to be suffering from “Sophomore System Syndrome” — over-architected, obsessed with its own power. I saw it as an ill-conceived blockbuster sequel, bloated with the developer’s equivalent of special effects and gratuitous action. Even the imagery surrounding it supported the analogy: the superhero’s emblem and the prominent number 2.
Having had a little more exposure now, though, I think I can see that simplicity and ease-of-use were in fact goals for the designers, and that some of the choices I saw as overly-complicated were in fact in service of that simplicity. The DI mechanism, for example, is equally as friendly to the developer as Angular 1’s, but more flexible. I will never accept that goofy template syntax, however.
It yet remains for me to use the framework on an actual project to determine whether its apparent benefits manifest in a real way. I’m eager to do so, though.