Note – This was last updated on 11/9/2015. The Angular team has since developed Angular CLI as a project starter platform, which has moved on to using WebPack 2.0 and provides lots of features such as testing and deployment features out of the box.
This blog entry is kept published for historical reasons.
Installing Gulp – our build tool
To do this work you'll need to install the gulp global
library. For the OSX and Linux users who installed Node as
Root, you'll need to prefix this with sudo. (Check out the
awesome nvm
project to run Node in userland,
and to install different versions of node, ala the Ruby rvm
version manager).
npm install -g gulp
The -g
flag forces npm
to install the gulp package
globally, which provides the command in your path for every project.
Next, you'll set up your Node project. Do something like this:
mkdir my-project cd my-project npm init
The npm init
command will take you through a series of
questions. Don't install a module system when prompted, take
the defaults on all items, including the entry point, and
allow it to save your new file, package,.json
.
Here are the contents of mine:
{ "name": "my-project", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
Install “local gulp” and the plugins we'll use
Next, we tell npm
to locally install the Gulp API.
Note:It is very important that we use the exact syntax below for
each local package, which both installs the package in node_modules
and marks the installation in the <devDependencies>
section of package.json
:
npm install --save-dev gulp
This test should output that both the CLI and local versions of Gulp
are installed and the versions match:
gulp -v [10:24:20] CLI version 3.9.0 [10:24:20] Local version 3.9.0
Set up the Gulp build script
In our project, we'll develop live code out of the web
directory, compiling TypeScript on-the-fly to web/js
and serving Angular and other features out of the web/lib
directory. These two tasks will be performed by gulp
, a
node-based development tool.
Let's create gulpfile.js
in the root of our project.
This is the file that gulp
will use to store its tasks:
var gulp = require('gulp'); gulp.task('setup', function(done) { gulp.src([ 'node_modules/angular2/bundles/js', 'node_modules/angular2/bundles/angular2.*.js*', 'node_modules/angular2/bundles/http.*.js*', 'node_modules/angular2/bundles/router.*.js*', 'node_modules/es6-shim/es6-shim.js*', 'node_modules/systemjs/dist/*.*', 'node_modules/jquery/dist/jquery.*js', 'node_modules/bootstrap/dist/js/bootstrap*.js', 'node_modules/@reactivex/rxjs/dist/global/Rx.js' ]).pipe(gulp.dest('web/lib')); gulp.src([ 'node_modules/bootstrap/dist/css/bootstrap.css' ]).pipe(gulp.dest('web/css')); });
This script defines a task, setup
, that can be invoked
from the shell in this way:
gulp setup
Although the files aren’t installed just yet, this task will copy the
right libraries for our ES5 + System.JS
config
into our library deployment directory, web\lib
.
There are better ways to do this work, including using a smarter
loading process, but I find teasing the files apart by hand helps
illustrate the dependencies an Angular2 project will actually need.
Adding our file management tasks
We’ll start out by defining a task for copying any static assets
from the src
directory to the web/
directory,
and we’ll call it assets
:
// called when we change our non-TypeScript assets gulp.task('assets', function() { gulp.src(['./src/**/*.json', './src/**/*.html', './src/**/*.css']) .pipe(gulp.dest('./web')); });
Note that the script above can be extended to support other file types, and
can easily copy to more than one location. Also note the general Gulp file
processing mechanism is to stream a series of files from one place to another.
Gulp tasks generally take source files and pass them through a chain of
plugins. So you can imagine it as a series of pipes:
// example gulp.src(['**/*.js', ...]).pipe(pluginOne({ ... }).pipe(pluginTwo({ ..})... gulp.dest('some.folder/');
Implementing a watchdog start task
We’ll also create a task that watches any files in the web/
directory, so that any changes there (for testing purposes) also
and we add our watcher top-level task, which delegates calls to the
tasks listed in the array at the end of the function:
Gulp has some pretty nifty ways to allow tasks to depend on each other.
For example, a task depends on another task if the second parameter of that task
is one task name, or an array of task names.
gulp.task('watch', ['watch.assets', 'watch.ts', 'watch.web']);
The task above, watch
, depends on firing off three other
tasks – watch.assets
, watch.ts
, and watch.web
.
Those files actually use the Gulp watch
function to observe files
and execute commands once the files themselves change.
A bare-bones asset pipeline
The first of these tasks, watch.assets
, copies any changed files
in ./src
when they change, and calls our assets
script
above to march them over to the ./web
directory.
// copies non-typescript assets by calling // the assets task when any source files change gulp.task('watch.assets', ['assets'], function() { return gulp.watch(['./src/**/*.json', './src/**/*.html', './src/**/*.css'], ['assets']); });
Stubbing out our TypeScript compiler
Up next, our TypeScript compiler. But we’re not ready to discuss that yet,
we want to keep this article focused on Gulp. So we’ll stub out the implementation
but provide the watcher now.
// calls the typescript compiler whenever // any typescript files change gulp.task('watch.ts', ['ts'], function() { return gulp.watch('src/**/*.ts', ['ts']); }); gulp.task('ts', function() { console.log('Typescript compilation here.'); });
This watcher keeps an eye on any TypeScript file (we’ll see in the next
post that TypeScript files have an extension of .ts
), and passes
it along to the TypeScript compiler task, ts
which we currently
just use to log a console message.
Finally, the web directory change detector
This one is overkill, but we’ll also watch web/
for any
changes, in case we’re just testing the effects of something in that directory.
// stubbed out function (to implement later) function notifyLiveReload() { } // if we change any files in the web directory // reload the page - this is for when we // update any of our assets with the // setup command or drop a file in the content // area of web like a css file... gulp.task('watch.web', function() { gulp.watch('web/**', notifyLiveReload); });
The default task – start ‘er up!
Finally, we give the user a default task, which launches
our three main backgrounders – express
, livereload
,
and watch
. You probably should run setup the first time,
so that you get the assets (and you may make setup
smarter).
gulp.task('default', ['express', 'livereload', 'watch']);
Now we’ll install our Angular libraries, System.JS and other dependencies and shims, so we can have something to
deploy with our setup
task
Angular libraries and dependencies install
Our Angular2 Runtime environment needs several key files:
angular2.dev.js
– the Angular2 ES5 library, running with theSystem.JS
module loaderhttp.dev.js
– the Angular2 network libraryrouter.dev.js
– the new Angular2 router for routing across viewssystem.js
– the System.JS ES5 Module runtime libraryes6-shim.js
– a shim file to support ES6 API features in ES5 browsers
Install these libraries into your NodeJS directory with the following commands (note how they don’t use --save-dev
,
only --save
– as there are no tools to add to your project’s path.
npm install --save angular2 system.js es6-shim
These libraries are optional and will be used in later posts:
npm install --save bootstrap jquery
Now you’re ready to move on to setting up the TypeScript compiler.
Series Table of Contents
- Overview
- Install Gulp and the file watcher pipeline (this document)
- Install TypeScript and the Gulp TypeScript process
- Install the Express Web Server and LiveReload