This post is part of a series of posts about Angular2. You can find them all in the introduction: https://julienrenaux.fr/2015/11/30/angular2-series-introduction/


Tooling is really important when starting a new project. This post presents my favorite tool stack (TypeScript & Webpack) and explain why you should use it too with Angular2.

Angular2 does not require any of the following tools, the choice is entirely yours to use them or not.

ECMAScript6

ECMAScript 2015 (6th Edition) is the current version of the ECMAScript Language Specification standard. ES6 got officially approved and published as a standard on June 17, 2015 by the ECMA General Assembly.

Angular 2 requires ES6 support, but ES6 is only available on modern browsers. For older browsers (including IE 11) you can use a shim to get the needed functionality.

<script src="../node_modules/es6-shim/es6-shim.js"></script>

If you use a compilation phase (using Gulp, Grunt, Webpack or Browserify), which I recommend (see last paragraph about Webpack) you could directly compile your ES6 code into ES5 instead of using es6-shim. ES5 is available on most browsers.

If you want to have a complete overview of what ES6 new features are, I recommend reading the this great babeljs doc

Class

Classes are used everywhere in Angular2, a Service is a Class, a Component is also a Class and a Directive is… a Class. It is therefore important to learn a bit about them.

ES6 introduced Classes (available for a long time in CoffeeScript). Classes are a simple sugar over the prototype-based object oriented pattern. If you come from an object oriented language such as Java, Php or C++ you are already accustomed to classes.

Here is simple example from a book that I love JavaScript Design Patterns by Addy Osmani:

class Car {
  constructor(model, km) {
    this.model = model;
    this.km = km;
  }
  drive(km) {
    this.km = this.km + km;
  }
  getKm() {
    return `${this.km} km`;
  }
}

Classes support inheritance, super calls and static methods.

Instantiation

Let’s play with our new car! We are going to instantiate a used car and drive it a little:

let twingo = new Car("Renault Twingo",100000);
console.log(twingo.getKm()); // dump: 100000 km

// Drive 150km
twingo.drive(150);
console.log(twingo.getKm()); // dump: 100150 km

Access static methods

class Car {
  ...
  static getWheels(){
    return 4;
  }
}

console.log(Car.getWheels()); // dump: 4

Calling getWheels static function on a Car instance twingo.getWheels() will result as twingo.getWheels is not a function..

All of these examples are available on plunker.


TypeScript

TypeScript is a super-set of ES6, meaning that when writing TypeScript code you have access to all ES6 new features such as arrow functions, generator, multiline strings etc. It also means that you can rename your ES6 based files from .js to .ts without any problem.

If you are used to ECMAScript6, jumping to TypeScript should not be difficult at all. While you are not forced to use TypeScript when developing Angular2 applications, I I still recommend using it for several reasons:

ES6 shim not needed anymore

TypeScript can also transform your code into ES5 (available on most browsers).

To do that, add a tsconfig.json file to the root of your project and specify the compile option to be ES5:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    ...
  }
}

Optional typing

TypeScript enables the optional typing. It means that if we want to force a type on a Class property we can do it that way:

export class Car {
    model: string;
    km: number;
    constructor(newModel: string, newKm: number) {
        this.model = newModel;
        this.km = newKm;
    }
    drive(km: number) {
        this.km = this.km + km;
    }
}

Here we made sure that the car model is a string and the car number of km is a number.

Now running new Car("Renault Twingo", "100000") (note that the second argument is a string) will return an error.

Interface

In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project.

Class Types

Interfaces are capable of describing the wide range of shapes that JavaScript objects can take. In addition to describing an object with properties, interfaces are also able to describe function types.

interface CarInterface {
    model: string;
    km: number;
    drive(km: number);
    getKm();
}

class Car implements CarInterface {
    model: string;
    km: number;
    constructor(newModel: string, newKm: number) {
        this.model = newModel;
        this.km = newKm;
    }
    drive(km: number) {
        this.km = this.km + km;
    }
    getKm() {
        return `${this.km} km`;
    }
}

Interfaces are a great feature to have. I personally use it when building applications that are Web and Mobile compatible.

With an interface, I expose common properties and methods that we can implement. Then, we can have CarMobile and CarWeb Classes that expose the same API but implement methods in a different way (for instance using Ionic service on mobile and Bootstrap service on Web).

IDE support

What I really like about TypeScript is the IDE support. Whether you use Atom, WebStorm or SublimeText you will still have plugins to enable autocompletion, type checking and linter.


Webpack

Webpack is a module bundler that is quite popular lately in the React community, but now also in the Angular2 community.

You can forget about Grunt or Gulp scripts that need to be maintained. Webpack allows you to require any type of file (.js, .coffee, .css, .scss, .png, .jpg, .svg, etc.) and pipe them through loaders to generate static assets, available to your application.

If you need examples on how Webpack works I suggest you go check out a previous post of mine: https://julienrenaux.fr/2015/03/30/introduction-to-webpack-with-practical-examples/.

Compilation phase

Having a compilation phase has a real advantage. It allows you to automate behavior that you have to do manually otherwise. For instance, autoprefixing your CSS to work with most of the Browsers.

The following CSS with -webkit- and -ms- prefixes is really painful to write manually because you need to know which prefix to use on different cases.

.page-wrap {
  display: -webkit-box;  /* OLD - iOS 6-, Safari 3.1-6, BB7 */
  display: -ms-flexbox;  /* TWEENER - IE 10 */
  display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
  display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
}

If you use a compilation phase you could just write it that way:

.page-wrap {
  display: flex;
}

The CSS is now lighter, easier to understand and to maintain.

Webpack allows you to “pipe” your CSS code into several loaders that will transform it. In that particular case, we want the autoprefixer loader to add prefixes compatible with the last 2 versions of all browsers.

{
    test: /\.css$/,
    loader: "style!css!autoprefixer?browsers=last 2 versions"
}

Catching syntax errors

Having a tool such as Webpack is great to catch potential JavaScript syntax errors even before running your code in the browser. With webpack-dev-server your code is compiled on the fly when any file is modified. Any syntax error will display this kind of message on your terminal:

ERROR in ./lib/home/controller.js
Module build failed: SyntaxError: /Users/shprink/Sites/test/controller.js: Unexpected token (6:39)
  4 |     var vm = this;
  5 |
> 6 |     $scope.$on('$viewContentLoaded' () => {
    |                                    ^
  7 |
  8 |     });
  9 |

Here we forgot to add a coma between '$viewContentLoaded' and our function.

Avoid CSS and template inline

ES6 introduces a really great feature which is multiline strings. Before ES6, a multiline string could be written that way:

"<h4>Give me some keys!</h4>" + 
"<div>{{values}}</div>"

or:

["<h4>Give me some keys!</h4>",
"<div>{{values}}</div>"].join('')

Now with ES6, you can write it that way:

`
    <h4>Give me some keys!</h4>
    <div>{{values}}</div>
`

This is really nice, but I am not a big fan of using it for HTML or CSS. In a lot of Angular2 examples you will see something like this:

@Component({
    selector: "app"
})
@View({
  styles: [`
     .container{
        color: red;
     }
  `],
  template: `
    <h4>Give me some keys!</h4>
    <div><input (keyup)="onKey($event)"></div>
    <div>{{values}}</div>
  `
})

While this is great for tutorials as it is concise and inline, it is, in my opinion, not good to use on your projects.

The reason is fairly simple. When using CSS or HTML into a JavaScript file you loose all the great features that your IDE provides. For instance, you cannot correctly format your HTML or CSS and you do not have autocompletion.

What I prefer to do is having separated HTML and CSS files so we can leverage IDE’ features on them. With Webpack you could do something like this to import your HTML and CSS as strings:

@Component({
    selector: "app"
})
@View({
    directives: [Navbar, RouterOutlet],
    styles: [require('./index.scss')],
    template: require('./index.html')
})

Thanks for reading, you can interact about this post by leaving a comment here, or directly on Twitter and Facebook!