We will quickly set up the project before we can start writing. We will use npm to manage our dependencies and gulp to build our project. These tools are built on NodeJS, so it should be installed from nodejs.org.
First of all, we must create a new directory in which we will place all files. We must create a package.json file used by npm:
The package.json file contains information about the project, such as the name, version, and a description. These fields are used by npm when you publish a project on the registry on NPM, which contains a lot of open source projects. We will not publish it there. We set the private field to true, so we cannot accidentally publish it.
Directory structure
We will separate the TypeScript sources from the other files. The TypeScript files will be added in the lib directory. Static files, such as HTML and CSS, will be located in the static directory. This directory can be uploaded to a webserver. The compiled sources will be written to static/scripts. We first install Angular and some requirements of Angular with npm. In a terminal, we run the following command in the root directory of the project:
The console might show some warnings about unmet peer dependencies. These will probably be caused by a minor version mismatch between Angular and one of its dependencies. You can ignore these warnings.
Configuring TypeScript
TypeScript can be configured using a tsconfig.json file. We will place that file in the lib directory, as all our files are located there. We specify the experimentalDecorators and emitDecoratorMetadata options, as these are necessary for Angular:
The target option specifies the version of JavaScript of the generated code. Current browsers support es5. TypeScript will compile newer JavaScript features, such as classes, to an es5 equivalent. With the lib option, we can specify the version of the JavaScript library. We use the libraries from es2015, the version after es5. Since these libraries might not be available in all browsers, we will add a polyfill for these features later on. We also include the libraries for the DOM, which contains functions such as document.createElement and document.getElementById.
Building the system
With gulp, it is easy to compile a program in multiple steps. For most webapps, multiple steps are needed: compiling TypeScript, bundling modules, and finally minifying all code. In this application, we need to do all of these steps.
Gulp streams source files through a series of plugins. These plugins can (just like gulp itself) be installed using npm:
The --global flag will install the dependency globally such that you can call gulp from a terminal. The --save-dev flag will add the dependency to the devDependencies (development dependencies) section of the package.json file. Use --save to add a runtime dependency.
We use the following plugins for gulp:
The gulp-typescript plugin compiles TypeScript to JavaScript
The gulp-uglify plugin can minify JavaScript files
The small plugin can bundle external modules
The gulp-sourcemaps plugin improves the debugging experience with source maps
We will create two tasks, one that compiles the sources to a development build and another that can create a release build. The development build will have source maps and will not be minified, whereas the release build will be minified without source maps. Minifying takes some time so we do not do that on the debug task. Creating source maps in the release task is possible too, but generating the source map is slow so we will not do that.
We write these tasks in gulpfile.js in the root of the project. The second task is the easiest to write, as it only uses one plugin. The task will look like this:
var gulp = require('gulp');
var uglify = require('gulp-uglify');
gulp.task('release', ['compile'], function() {
return gulp.src('static/scripts/scripts.js')
.pipe(uglify())
.pipe(gulp.dest('static/scripts'));
});
The gulp.task call will register a task named release, which will take static/scripts/scripts.js (which will be created by the compile task), run uglify (a tool that minifies JavaScript) on it, and then save it in the same directory again. This task depends on the compile task, meaning that the compile task will be run before this one.
The first task, compile, is more complicated. The task will transpile TypeScript, and bundle the files with the external libraries.
First, we must load some plugins:
var gulp = require('gulp');
var typescript = require('gulp-typescript');var small = require('small').gulp;var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify');
We load the configuration of TypeScript in the tsconfig.json file:
var tsProject = typescript.createProject('lib/tsconfig.json');
Now, we can finally write the task. First, we load all sources and compile them using the TypeScript compiler. After that, we bundle these files (including Angular, stored under node_modules, using small):
This task compiles our project and saves the result as static/scripts/scripts.js. The sourcemaps.init() and sourcemaps.write('.') functions handle the creation of source maps, which will improve the debugging experience.
The HTML file
The main file of our application is the HTML file, static/index.html. This file will reference our (compiled) scripts and stylesheet: