AngularJS and TypeScript
A journey through our stack
Who we are
Santi Albo
@Curial
Jamie McCrindle
@foldr

bn.co
Our Front End Stack

AngularJS
TypeScript
Yeoman
IntelliJ
AWS S3
MaxCDN

Javascript with Types
Developed by Microsoft
Apache Licensed
Works on Mac OS X and Linux using Node
Why TypeScript?
Type Safety
Type Definitions for Javascript
IDE Support
Smart Code Completion
Refactoring
Some of ES6 Now
Some of ES6 Now
Arrow functions
(name) => "Hello " + name;
Default Arguments
function hello(name="World") { return "Hello " + name; }
Classes
class Greeter { constructor(name) { this.name = name; } }
Modules
module greeters { /* encapsulated code */ }
Type Safety and Inference
var helloString = "Hello World"!;
var helloArray = ["Hello World!"];
function helloFunction(name) { return "Hello " + name + "!"; }
Type Safety and Inference
var helloString : string = "Hello World!";
var helloArray : string[] = ["Hello World!"];
function helloFunction(name : string) : string {
return "Hello " + name + "!";
}
var helloString : string = "Hello World!";
var helloArray : string[] = ["Hello World!"];
function helloFunction(name : string) : string { return "Hello " + name + "!"; }
Compiled to Javascript
var helloString = "Hello World!";
var helloArray = ["Hello World!"];
function helloFunction(name) {
return "Hello " + name + "!";
}
//# sourceMappingURL=test.js.map
IDE Support

Visual Studio

Web Storm and IntelliJ

Plugins for vim, Sublime Text, emacs


Writing an AngularJS App in TypeScript

References
/// <reference path="types/angularjs/angular.d.ts"/>
/// <reference path="types/angularjs/angular-route.d.ts"/>
/// <reference path="types/restangular/restangular.d.ts"/>
Type definitions make Javascript type safe
interface IRouteProvider extends IServiceProvider {
otherwise(params: any): IRouteProvider;
when(path: string, route: IRoute): IRouteProvider;
}
interface IRoute {
controller?: any;
controllerAs?: any;
name?: string;
template?: string;
templateUrl?: any;
resolve?: any;
redirectTo?: any;
reloadOnSearch?: boolean;
}
Routing
angular.module("myApp", ["ngRoute", "restangular"])
.config(["$routeProvider",
($routeProvider: ng.route.IRouteProvider) => {
$routeProvider
.when("/", {
templateUrl: "views/main.html",
controller: "MainCtrl",
resolve: {
entries: ["Restangular", (Restangular: Restangular) => {
return Restangular.all("entries").getList();
}]
}
})
.otherwise("/")
}]);
Controllers
class MainCtrl { constructor(private $scope, public entries: ArrayRest<IEntryRest>) { $scope.vm = this; } // ... public upvote(entry: IEntryRest) { // POST on /entries/:entryId/upvote entry.post("upvote", {}).then((updatedEntry: IEntryRest) => { entry.votes = updatedEntry.votes; }); } }
angular.module("myApp")
.controller('MainCtrl', ['$scope', 'entries', MainCtrl]);
Building and Deploying using Grunt

Grunt tasks
Grunt is a Javascript 'Task' runner
Tasks are defined in the Gruntfile.js
The Gruntfile.js is just a node.js script
Tasks are defined in the Gruntfile.js
The Gruntfile.js is just a node.js script
$ grunt test
$ grunt server
$ grunt build
$ grunt deploy
Run the tests

Unit testing with Karma and Phantom JS

End to end tests with Selenium

Configuration
Config for development, QA and production
Available as an AngularJS service called 'config'
Grunt inserts the correct environment config into the service when we build
var config: Config;
//@@config;
angular.module('labs.common.services').constant('config', config);
Building the app
- Compile the TypeScript files and embeds the settings file
- Compile the less files
- Concat everything within blocks in the index.html file
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/app.js"></script>
<script src="scripts/controllers/controllerA.js"></script>
<script src="scripts/services/serviceB.js"></script>
<!-- endbuild -->
- Minify the resulting css and js files
- Append the hash of the file to the name as a cache buster
- Replace libraries with a CDN version
- Put everything in a folder ready for deployment
Deploying to S3
Deploy into S3 folder using grunt-aws-s3
var folder=timestamp + "-" + git_commit_hash
e.g. 201401091540-fc90307
Set expiry headers for index.html
params: { Cache-Control: max-age=300 }
Update CDN
We wrote our own grunt-netdna library
Updates the pull zone to use the new S3 URL
Calls purge on the pull zone to clear out data
A few more things
Definitely Typed
If you need to depend on the latest version append the git commit hash to the url to avoid breaking future builds
Setting up the Gruntfile
Setting up the Gruntfile can take time but it's well worth it as it can automate a lot of your workflow
NPM shrinkwrap
Use npm shrinkwrap to manage your dependencies> npm shrinkwrap
NPM registry
Switch to the EU npmjs registry mirror
npm --registry http://registry.npmjs.eu/ install
npm set registry http://registry.npmjs.eu/
Thank you
@Curial
@foldr
typed-angular
By jamiemccrindle
typed-angular
- 3,995