grunt-ts

Compile and manage your TypeScript project

npm install grunt-ts
140 downloads in the last day
526 downloads in the last week
2 574 downloads in the last month

grunt-ts

Build Status NPM version

Written from scratch TypeScript compiler task for GruntJS. It differs from grunt-typescript which is another excellent grunt plugin for TypeScript.

Following are the reasons why grunt-ts was created:

  • Written in TypeScript
  • Enables a TypeScript development workflow in addition to simple file compilation.
  • Supports overriding the bundled compiler with an alternate version.

Check how grunt-ts can help streamline front end development: Sample usage with AngularJS

Additional / longer / more basic video tutorial: http://youtu.be/Km0DpfX5ZxM

For a quickstart see the full featured Gruntfile.

Key features

Compiler support

Supports the following compiler flags in both original format and camelCase (preferred):

--allowBool                   Allow 'bool' as a synonym for 'boolean'.
--allowImportModule           Allow 'module(...)' as a synonym for 'require(...)'.
--declaration                 Generates corresponding .d.ts file
--mapRoot LOCATION            Specifies the location where debugger should locate map files instead of generated locations.
--module KIND                 Specify module code generation: "commonjs" or "amd" (grunt-ts default)
--noImplicitAny               Warn on expressions and declarations with an implied 'any' type.
--noResolve                   Skip resolution and preprocessing
--removeComments              Do not emit comments to output (grunt-ts default)
--sourceMap                   Generates corresponding .map file (grunt-ts default)
--sourceRoot LOCATION         Specifies the location where debugger should locate TypeScript files instead of source locations.
--target VERSION              Specify ECMAScript target version: "ES3" (tsc default), or "ES5" (grunt-ts default)

There is also support for js file concatenation using --out. Additionally supported is an output directory for the generated JavaScript using --outDir flag. For file ordering look at JavaScript Generation below.

Reference file generation

Grunt-ts can generate a reference.ts file which contains a reference to all ts files.

This means there will never be a need to cross reference files manually, instead just reference reference.ts :)

JavaScript generation and ordering

When a output file is specified via out in combination with a reference file via reference then grunt-ts uses the generated reference file to order the code in the generated JavaScript.

Use reference.ts to specify the order for the few files the build really cares about and leave the rest to be maintained by grunt-ts.

E.g. in the following case the generated JavaScript for someBaseClass.ts is guaranteed to be at the top, and the generated JavaScript for main.ts is guaranteed to be at the bottom of the single merged js file.

Everything between grunt-start and grunt-end is generated and maintained by grunt-ts. If there is no grunt-start section found, it is created. If reference.ts does not exist originally, it is also created.


/// <reference path="someBaseClass.ts" />

// Put comments here and they are preserved

//grunt-start
/// <reference path="autoreference.ts" />
/// <reference path="someOtherFile.ts" />
//grunt-end


/// <reference path="main.ts" />

JavaScript generation redirect

If an outDir is specified all output JavaScript is redirected to this folder to keep the source folder clean.

AMD / RequireJS support

When both outDir and amdloader options are specified a JavaScript requireJS loader file is created using the information available from reference.ts.

The file consists of three sections.:

  • The initial ordered section.
  • A middle order independent section loaded asynchronously.
  • And a final ordered section.

E.g the following reference file:

/// <reference path="classa.ts" />

//grunt-start
/// <reference path="deep/classb.ts" />
/// <reference path="deep/classc.ts" />
//grunt-end

/// <reference path="deep/deeper/classd.ts" />
/// <reference path="app.ts" />

This corresponds to an amdloader (edited for readability):

// initial ordered files
define(function (require) {
  require(["./classa"],function () {
    // grunt-ts start
    require(["./deep/classb",                       
             "./deep/classc"],function () {
      // grunt-ts end
      // final ordered files
      require(["./deep/deeper/classd"],function () {  
        require(["./app"],function () {
          // final ordered file loaded
        });
      });
    });
  });
});
Advantage of using amdloader option

The following combination of circumstances are the main use-case for amdloader compared to the original Compiler supported AMD:

  • Use RequireJS since allows to debug "js" files instead of "ts" files. This is useful in some cases, the most common way is using AMD.
  • Keep the ability to individually compile only changed files (for a faster dev-compile-run cycle)
  • However, File order doesn't matter, even when there is a inter file depenendency (e.g. AngularJS runtime Dependency injection)

In such a case it is possible to either create a loader.js manually or have grunt create one.

Further Explanation When using export class Foo{} at the root level of the file the only way to use the type information of Foo in another file is via an import statement: import foo = require('./potentially/long/path/to/Foo');.

The ordering implied by this isn't necessary when using a runtime Dependency Injection framework like AngularJS.

Having a loader gives the js debugging (+ async) advantages of RequireJS without the overhead of constantly requesting via import to get the TypeScript type inference and worrying about file paths when they are not relevant.

Note: the individual file source-map will continue to work so it is possible to debug individual "JS" or "TS" files :)

Html 2 TypeScript support

Grunt-ts can re-encode html files into TypeScript and make them available as a variable.

For example a file called test.html:

<div> Some Content </div>

Will be compiled to a TypeScript file test.html.ts containing:

module test { export var html =  '<div> Some content </div>' }

This will export the variable test.html within the TypeScript scope to get the content of test.html as a string, with the main benefit of limiting the http-requests needed to load templates in various front-end frameworks.

Html 2 TypeScript usage in AngularJS

This is great for putting variables in templateCache: http://docs.angularjs.org/api/ng.$templateCache or even using the html string directly by setting it to the template properties (directives/views) instead of templateUrl

Html 2 TypeScript usage in EmberJS

It is possible to specify this string to the template on a view: http://emberjs.com/api/classes/Ember.View.html

Specifically: http://stackoverflow.com/a/9867375/390330

Live file watching and building

Grunt-ts can watch a directory and recompile TypeScript files when any TypeScript file changes, gets added, gets removed. Internallythe chokidar module is used to makes sure the project is always build ready :)

Installation

Grunt-ts is published as npm package:

For new projects make sure to have installed nodejs, then install grunt-cli:

$ npm install -g grunt-cli

Install the and save to package.json devDependencies:

$ npm install grunt-ts --save-dev

Alternate compiler version

Support for both legacy or cutting-edge projects can be enabled using the compiler override:

At runtime the plugin will look for an alternate compiler in the same node_modules folder. To use a different version of the TypeScript compiler install the required typescript version as a peer of grunt-ts. If no override was found the bundled compiler is used.

The package.json would look something like this for a legacy project:

{
  "devDependencies": {
    "grunt" : "~0.4.1",
    "grunt-ts" : "~1.9.2",
    "typescript" : "0.9.7"
  }
}

Note: make sure to pin the exact TypeScript version (do not use ~ or >).

Configuration

Create a Gruntfile.js. Modify it to load grunt-ts by adding the following lines:

module.exports = function (grunt) {

    // load the task 
    grunt.loadNpmTasks("grunt-ts");

    // Configure grunt here
}

Add some configuration for the plugin:

grunt.initConfig({
    ...
    ts: {
        // A specific target
        build: {
            // The source TypeScript files, http://gruntjs.com/configuring-tasks#files
            src: ["test/work/**/*.ts"],
            // The source html files, https://github.com/grunt-ts/grunt-ts#html-2-typescript-support   
            html: ["test/work/**/*.tpl.html"], 
            // If specified, generate this file that to can use for reference management
            reference: "./test/reference.ts",  
            // If specified, generate an out.js file which is the merged js file
            out: 'test/out.js',
            // If specified, the generate JavaScript files are placed here. Only works if out is not specified
            outDir: 'test/outputdirectory',
            // If specified, watches this directory for changes, and re-runs the current target
            watch: 'test',                     
            // Use to override the default options, http://gruntjs.com/configuring-tasks#options
            options: {     
                // 'es3' (default) | 'es5'
                target: 'es3',
                // 'amd' (default) | 'commonjs'    
                module: 'commonjs',
                // true (default) | false
                sourceMap: true,
                // true | false (default)
                declaration: false,
                // true (default) | false
                removeComments: true
            },
        },
        // Another target
        dist: {                               
            src: ["test/work/**/*.ts"],
            // Override the main options for this target
            options: {
                sourceMap: false,
            }
        },
    },
    ...
});

It is recommended to add a default target to run in case no arguments to grunt are specified:

grunt.registerTask("default", ["ts:build"]);

For an example of an up-to-date configuration look at the sample gruntfile

Different configurations per target

Grunt-ts supports the Grunt convention of having multiple configuration targets per task. It is convenient to have one set of default options and then override these selectively for a target (e.g build , dev, staging etc).

Awesome file globs

For advanced use-cases there is support for Grunt's selection options, such as using globbing or using a callback to filter paths.

Contributing

With npm and grunt-cli installed, run the following from the root of the repository:

$ npm install

Building the project:

To build all

$ grunt build

Running the tests:

To test all

$ grunt test

Before PR

$ grunt release

It runs build followed by test. This is also the default task. You should run this before sending a PR.

Development

You will probably be working and testing a particular feature. Modify tasksToTest in our Gruntfile.js and run:

$ grunt dev

It will watch your changes (to grunt-ts task as well as examples) and run your tasksToTest after updating the task (if any changes detected).

License

Licensed under the MIT License.

npm loves you