Package Management for TypeScript Cordova Apps in Visual Studio

Visual Studio Tools for Apache Cordova

Visual Studio Tools for Apache Cordova is a Visual Studio extension for developing Cordova apps inside Visual Studio. It is bundled with Visual Studio 2015 and can be added as a feature when installing Visual Studio or at a later time by accessing the installer from Programs and Features dialog in Windows. Detailed installation and update instructions are included in the official documentation.

Tools for Apache Cordova feature in Visual Studio installer

With the extension installed, two Cordova project templates become available in Visual Studio: a JavaScript based one and a TypeScript based one. They only differ in the language they are preconfigured for, so you'll choose the one you plan to develop in. For the purpose of this post, I chose the TypeScript one.

Cordova projects available in Visual Studio

Installing JavaScript Packages

You'll want to use existing JavaScript libraries in your Cordova project. To avoid managing the referenced libraries by hand you should use one of the package managers. I chose Bower as the one designed with front end libraries in mind.

Make sure you have Bower installed globally, then invoke the following commands to initialize the project for saving the installed packages, and install the first package:

bower init
bower install angular --save

Alternatively you could install packages with Visual Studio's dialog for managing Bower packages (accessible from Solution Explorer) or with Mads Kristensen's Package Installer extension.

Manage Bower Packages from Solution Explorer context menu

Either way, installed Bower packages will by default end up in bower_components folder in the root of your project. Since this folder will not be packaged with the application, the files will somehow need to be delivered to the www folder. Although you could achieve this by changing the target directory for Bower packages, it would not be ideal, because not all the files in a Bower package are meant for distribution with the application.

If you want to only include the files that are actually needed by the library, you will need to use a task runner. In this post I am going to use Gulp, but the same could also be achieved with Grunt. To copy the installed libraries to www/scripts/lib, you will have to create a file named gulpfile.js in the root of the project with the following contents:

var gulp = require("gulp");
var mainBowerFiles = require('gulp-main-bower-files');

gulp.task("main-bower-files", function () {
    return gulp.src('./bower.json')
        .pipe(mainBowerFiles())
        .pipe(gulp.dest("./www/scripts/lib"));
});

You can install Gulp and the required plugin with NPM:

npm install gulp --save-dev
npm install gulp-main-bower-files --save-dev

All that's left, is making sure that the script will be run as part of Visual Studio build process. You can do that using Task Runner Explorer in Visual Studio - just add the main-bower-files task to Before Build binding.

Gulp task bindings in Task Runner Explorer

This will add a single line at the top of gulpfile.js, which you could as well add yourself manually instead of using the dialog above:

/// <binding BeforeBuild='main-bower-files' />

Installing TypeScript Definitions

For effective TypeScript development you will also want to install TypeScript definitions (i.e. so-called typings) for the libraries, which you are using. Typings for most libraries are not included in their distribution packages; they are available from a separate repository, named DefinitelyTyped.

For managing typings in a project, a TypeScript Definition manager comes in handy. Historically this has been TSD, but it recently became deprecated in favor of a new one, named Typings.

Just like the other tools, it needs to be installed as a development dependency, using NPM:

npm install typings --save-dev

Unlike installed NPM and Bower packages, Visual Studio will not automatically restore the installed typings. You'll need to take care of that yourself, e.g. by hooking into NPM's restore process with a prepublish script that will be invoked as its last step. To do that, add a script block at the root level of package.json:

"scripts": {
  "prepublish": "typings install"
}

There's no working Visual Studio tooling available for Typings, yet. Even support for it in Package Installer is broken because of a breaking change that was introduced with version 1.0. Hence, for the time being you're stuck with using it from command line. E.g. you can install typings for angular with the following command:

typings install dt~angular --global --save

The dt~ prefix in the package name indicates DefinitelyTyped as the repository to use. The --global switch tells Typings that the definitions are still in the legacy global format. This should change eventually, but at the moment it makes it inconvenient to install typings with external dependencies. These are currently stripped by the tool and need to be individually installed manually. E.g. the above command for installing angular typings will result in the following output:

typings INFO reference Stripped reference "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/cec53b2710e2cc07e44d6260fc25d13ae21d640c/jquery/jquery.d.ts" during installation from "angular" (main)    
angular
└── (No dependencies)

The stripped jquery dependency must be installed manually with the following command:

typings install jquery="https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/cec53b2710e2cc07e44d6260fc25d13ae21d640c/jquery/jquery.d.ts" --global --save

As you can see, the complete file URL is used as location. Additionally, the name must also be explicitly set to the typings filename without the .d.ts. extension. You can imagine that installing typings for libraries with many dependencies, such as cordova can become quite tedious.

The Cordova project expects the installed typings in scripts/typings, therefore you'll need to change the default target directory in typings.json by adding the following at its root level:

"resolution": "scripts/typings"

Source control

If you don't want to add files to source control, when they can be recreated or restored from an external repository, you should exclude the following folders from source control:

  • node_modules, which contains installed NPM packages
  • bower_components, which contains installed Bower packages
  • scripts/typings, which contains installed Typings packages
  • www/scripts, which contains JavaScript files compiled from TypeScript files in scripts or copied from installed Bower packages

All of the files in these folders will be restored as part of the configured build process, unless one of the repositories or a package in it suddenly becomes unavailable.

Copyright
Creative Commons License