Feb 28, 2015

TypeScript + Gulp + Bower + Browserify

I just spend a few hours trying to use TypeScript in my Gulp task, so it can be used also with browserify and bower modules. Now when I see the result it’s really easy.

I used to write all my scripts in CoffeeScripts. The problem with that was that it felt strange. Maybe even wrong to me. I was like I could write almost anything and it will be magically compiled to javascript.

CoffeeScript is great language, but about my opinion too easy to write. After few years with CoffeeScript I wanted (again) try to use TypeScript. The reason for that is that I wanted something more robust, ideally with type system etc.

I’m also using Gulp with Bower and Browserify, so I thought that it would be easy to add support for TypeScript. Well… It is not….. At least my first attempts were not and there were many of them…

But lets see working code.

Gulp task

var gulp = require('gulp');

var source = require('vinyl-source-stream');
var browserify = require('browserify');
var tsify = require('tsify');

var config = {
	publicPath: __dirname + '/www/public',
	app: {
		path: __dirname + '/www/app',
		main: 'index.ts',
		result: 'application.js'
	}
};

gulp.task('compile-js', function() {
	var bundler = browserify({basedir: config.app.path})
		.add(config.app.path + '/' + config.app.main)
		.plugin(tsify);
	
	return bundler.bundle()
		.pipe(source(config.app.result))
		.pipe(gulp.dest(config.publicPath));
});

Great, with that I can compile TypeScript files with Browserify because of great module tsify.

Bower support

It seems that there is plugin or transform module for Browserify for everything. We can just install debowerify which will transform all our Bower imports.

Just update Gulp task:

// ...
var debowerify = require('debowerify');
// ...

var config = {...};

gulp.task('compile-js', function() {
	var bundler = browserify({basedir: config.app.path})
		.add(config.app.path + '/' + config.app.main)
		.plugin(tsify)
		.transform(debowerify);    // add this line
	
	return bundler.bundle()
		.pipe(source(config.app.result))
		.pipe(gulp.dest(config.publicPath));
});

And that’s it!

jQuery, Bootstrap, …

Now I can use jquery in nice way, but some foreign libraries need jquery in global object (window).

index.ts:

import jQuery = require('jquery');
window['jQuery'] = window['$'] = jQuery;

import Bootstrap = require('bootstrap');
Bootstrap['__loaded__'] = true;

The Bootstrap['__loaded__'] part is definitely not nice and shouldn’t be there, but TypeScript compiler will not compile unused imports so I needed to actually do something with Bootstrap variable.

Edit:

Using the __loaded__ trick above wasn’t really a good idea. Much better is eg. creating array. Also it looks much better:

import jQuery = require('jquery');
import Bootstrap = require('bootstrap');

[jQuery, Bootstrap];

Edit 2

I added sourcemaps, so check out created repo on GitHub.