Browse Tag: typescipt

Gulp in Visual Studio

This post walks through the basics of using Gulp in Visual Studio 2013. Specifically, we will add two compile time tasks; one for linting TypeScript files, and another for linting SCSS. You are not limited to using just linters with Gulp, in fact you can do just about anything.

Gulp is specifically good at running repetitive tasks and is widely used in the non-.NET world via the command line. Other common tasks include; minification, compilation and running unit tests. Fortunately for us, some unofficial tools have been developed by Microsoft (specifically, the awesome Mads Kristensen and his dedicated team) which enable us to use Gulp directly inside Visual Studio.

Gulp is JavaScript configuration based, meaning you configure Gulp via a special file called GulpFile.js, which you add to your project.

This post specifically targets Visual Studio 2013, because at the time of writing Visual Studio 2015 hasn’t been released yet (its actually RC at this point). As Microsoft tooling is evolving rapidly at this time, i’ll avoid covering 2015 for now (however, I may revise this post after Visual Studio 2015 is released).

This post is a fork of the popular post Grunt In Visual Studio 2013.

Prerequisites

NodeJS and npm

Gulp is built on top NodeJS and is installed via the Node Package Manager (npm). Both of these tools need to be installed to use Gulp. Check that you already have NodeJS installed, and/or download the latest version. The installation is a trivial process, so I wont document it fully here, but please ensure that the “npm package manager” feature is installed. This feature is selected by default, and it is need to install Gulp (and indeed, any other package).

Gulp

Before we can use Gulp, we must install it globally.

Open a command prompt and type

npm install -g gulp

You might want to get reacquainted with running commands in this way because with the rapid state of change in the industry, development of visual tools is always going to lag behind (even with Microsoft’s new rapid development and deployment ethos, but that’s a whole other discussion).

Task Runner Explorer

This tool will run our Gulp tasks for us. It will parse our Gulp File (which we will create shortly), list our tasks, let us run our tasks individually, and let us bind our tasks to “IDE events” (pre-build, after build, clean & solution open).

To install Task Runner Explorer, go to Tools > Extensions and Updates and type Task Runner Explorer. The first result should by created by Microsoft Corp.

Task Runner Explorer

Task Runner Explorer

Local Gulp

Now that we have the necessary tooling installed, we need to add Gulp to our actual project (and any additional packages we want to use). Packages are controlled using a special file called package.json. This file contains metadata about your project, and the packages its dependent on (and potentially a bunch of other stuff that is out of the scope of this tutorial).

Create a file called package.json at the root of your project, and add the following code;

{
    "name": "Gulp101",
    "version": "1.0.0",
    "devDependencies": {
        "gulp": "~3.9.0",
        "gulp-scss-lint": "~0.2.1",
        "gulp-tslint": "~3.1.0-beta"
    }
}

The file is pretty self explanatory, but if you want a little more information with regards to versioning, see this useful post; Node and npm Version Numbering: Guide and Best Practices.

To save time later, I have also included the other development dependencies. In this case, our TypeScript linter (gulp-tslint) and SCSS linter (gulp-scss-lint). We will configure these shortly.

To install the dependencies, open a command prompt and change the directory to that which contains your newly created package.json and run the following command;

npm install

This will result in a new directory being created, called node_modules, which will contain each dependency.

GulpFile.js

As previously mentioned, Gulp is a JavaScript based task runner. Gulp is configured/controlled using a file called Gulpfile.js. This file is responsible for defining the configuration for each task. You can have many tasks and many aliased groups that run multiple tasks.

For this tutorial we are going to validate our TypeScript and SCSS code quality using linters. Specifically, Gulp has packages called Gulp-TSLint and Gulp-SCSS-Lint (you defined and installed these packages earlier).

Add the following configuration;

var gulp = require('gulp');

var scsslint = require('gulp-scss-lint');
gulp.task('scss-lint', function () {
    gulp.src('/stuff/*.scss')
      .pipe(scsslint());
});

var tslint = require('gulp-tslint');
gulp.task('tslint', function () {
    return gulp.src('stuff/*.ts')
      .pipe(tslint())
      .pipe(tslint.report('verbose'));
});

gulp.task('typescript', ['scss-lint', 'tslint']);

Again, the beauty of Node and Gulp especially is that its pretty simple to understand what’s going on, even for a beginner.

SCSS Lint Task

The minimum configuration required is the path to your SCSS files, using the src method. In the given example, we simply find all the files in a sub directory with the extension *.scss. You can make this more complicated, and recursive, as follows;

Content/**/*.scss

This will recursively find every SCSS file in all folders sitting below the Content folder.

There’s a comprehensive tutorial on how to further refine the configuration on the NPM website. The documentation on GitHub is also excellent.

TS Lint Task

Before you can lint a TypeScript file, you must define some rules that you want to enforce throughout your code-base. You can push this configuration to source control and share with your team for maximum consistency.

If you have Web Essentials installed (and I highly recommend all web developers install this excellent tool) then you can quickly generate a configuration file by clicking Web Essentials > Edit Global TSLint Settings (tslint.json). Clicking this drops a tslint.json file into your Documents folder and opens it directly in Visual Studio, where you can make edits. I highly recommend closing the file, moving it into your solution folder, and adding it as part of your project for easy access later.

If you don’t use Web Essentials are you insane? you can grab a sample configuration file directly from the GitHub source code repository and again I recommend that you add it as part of your project. I won’t go into the ins and outs of each of the TypeScript linting rules, that’s for another time. Just know that you can change them to your hearts content.

As with the SCSS linter, you specify the path of your TypeScript files using the src method. You pass in a string that represents the path of your TypeScript files.

gulp.src('stuff/*.ts')

Final Steps

Add some code

There is just one more step we need to take before running our tasks, we need some code to test!

Add a new SCSS file to your project, and a new TypeScript file. Add the following beautifully written ugly code to the TypeScript file;

module SomeModule {

    export class SomeClass {

        str: string;

        constructor() {
            this["str"] = "Hello, World"
        }
    }
}

The main issues with this code are trailing whitespace, no "use strict", missing semi-colons and access to a property via a string literal. We will let Gulp tell us about these shortly.

Open the task runner

Open the task runner by going to View > Other Windows > Task Runner Explorer.

Select your project (if it is not selected by default) and click the refresh button. Your Gulpfile.js configuration file should be loaded and the alias tasks and individual tasks should be displayed.

You can manually run a task (or set of tasks) by right clicking and selecting Run. If all went well, you should see the following output;

c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp> cmd.exe /c gulp -b "c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp" --color --gulpfile "c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp\gulpfile.js" typescript
[13:48:21] Using gulpfile c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp\gulpfile.js
[13:48:21] Starting 'scss-lint'...
[13:48:21] Finished 'scss-lint' after 5.33 ms
[13:48:21] Starting 'tslint'...
[13:48:21] [gulp-tslint] error (no-string-literal) helloworld.ts[8, 18]: object access via string literals is disallowed
[13:48:21] [gulp-tslint] error (semicolon) helloworld.ts[8, 41]: missing semicolon
[13:48:21] [gulp-tslint] error (use-strict) helloworld.ts[1, 1]: missing 'use strict'
[13:48:21] 'tslint' errored after 68 ms
[13:48:21] Error in plugin 'gulp-tslint'
Message:
    Failed to lint: helloworld.ts[8, 18]: object access via string literals is disallowed, helloworld.ts[8, 41]: missing semicolon, helloworld.ts[1, 1]: missing 'use strict'.
Process terminated with code 1.

Success! Wait what? Oh yes, the task has failed because our TypeScript file has lots of linting errors. Open up the TypeScript file and use the output message to fix each problem. Once done re-run the task again by right clicking and clicking run. Once all issues are resolved, you should get the following;

c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp> cmd.exe /c gulp -b "c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp" --color --gulpfile "c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp\gulpfile.js" typescript
[13:49:12] Using gulpfile c:\Users\jon.preece\Documents\Visual Studio 2013\Projects\gulp\gulp\gulpfile.js
[13:49:12] Starting 'scss-lint'...
[13:49:12] Finished 'scss-lint' after 5.36 ms
[13:49:12] Starting 'tslint'...
[13:49:12] Finished 'tslint' after 64 ms
[13:49:12] Starting 'typescript'...
[13:49:12] Finished 'typescript' after 7.33 μs
Process terminated with code 0.

Bindings

Right clicking and clicking run is a little too manual for my liking, this is an automation tool isn’t it? Alas, the Task Runner Explorer provides you with Bindings. Basically you can hook in to events in the IDE and run your tasks automatically when one of events happens.

Available bindings;

  • Before Build
  • After Build
  • Clean
  • Solution Open

To bind a task to a binding, right click the task (or again, the aliased task) and select Bindings > {An IDE Event of your choice}. In my case, I have chosen Before Build. So when I press Ctrl+Shift+B the tasks are ran automatically.

Note that as far as I know, you can’t fail the build if a task fails at this point. No doubt this is an upcoming feature.

Summary

Gulp is a brave new world for most .NET developers. Tooling is certainly in its infancy (within Visual Studio) at this point, but the awesome power of NodeJS, npm and Gulp can be harnessed with some useful extensions.

What I learnt from using TypeScript “for real”

I completed my first commercial Greenfield project using TypeScript over plain old JavaScript throughout, and there were some frustrations along the way.

 

TL;DR

  • TypeScript is awesome, for sure, but there needs to be improvements to tooling to streamline the experience.
  • TypeScript is strongly typed of course, but it doesn’t force you to code in this manner, which can result in shoddy code.
  • Tweaking is required to make bundling work properly.

 

Tooling Frustrations

When I started the project, I was using Visual Studio 2012 Update 4 with TypeScript 1.0 pre-installed.  I was brought in to work on this project on a short term basis, and this is how the machine was set up when I arrived.  Normally I wouldn’t choose to use Visual Studio 2012 (I like to use the latest tools where possible) but I decided to just go with it and make do.  Once deficiencies in tooling became clear, I did eventually push for an update to Visual Studio 2013 Update 4, which in fairness resolved most of my frustrations.

I have a license for JetBrains ReSharper, which has support for TypeScript 1.4 (and indeed that is the default setting when using ReSharper 9).  This was actually my first tooling problem.

When using Visual Studio 2012, you are using TypeScript 1.0 (unless you have proactively updated to version 1.4).  Naturally 1.0 is an older version and doesn’t support language features such as protected methods or ECMAScript 6 template strings.  ReSharper, however, does understand these features and offers suggestions to use them.  Trying to use these features results in build errors, which of course was confusing because I didn’t understand that I was actually using version 1.0 at the time (does it say anywhere? not to my knowledge).

Also, due to the aforementioned old version of TypeScript, I also encountered an issue with TypeScript definition files.  These files are designed to not only provide IntelliSense in Visual Studio when working with third party libraries such as AngularJS, but also are used during the build process for compile time checking.  Because the TypeScript definition files (sourced using NuGet via GitHub) were based on TypeScript 1.4, again hundreds of errors at compile time.  Interestingly, however, with version 1.0 it was actually possible to ignore these build errors and still generate the compiled JavaScript files.  Only once upgrading to version 1.4 later on did it become mandatory to fix these build issues.

Compile on save does what it says on the tin.  You write some TypeScript code, click Save, and the JavaScript file is generated automatically.  Well, actually, no.  There were dozens of occasions when this just didn’t work.  I had to literally open the scripts folder, delete the JavaScript files manually, re-open Visual Studio, and save the TypeScript file again before it would actually recompile the JavaScript file.  This was tedious and boring and didn’t seem to be resolved by upgrading to Visual Studio 2013 Update 4 (although it did become less frequent).  I have Web Essentials installed, which gives you a side by side view of the TypeScript and JavaScript files which I originally turned off.  I did eventually turn this back on so I could see if the files were being recompiled at a glace before refreshing the web browser.

On a side note, the tooling provided by Google Chrome developer tools is excellent.  You can debug the actual TypeScript source directly in the browser, and if you inadvertently set a breakpoint on a JavaScript file, Chrome will navigate you back to the TypeScript file.  Nice.

 

Bundling in MVC

The project I was working on used some features of ASP .NET and Web API.  One such feature was bundling and minification, which I always use to improve performance and reduce server load.  I wrote many based files and interfaces as you would expect, as both are fully supported in TypeScript.  However, what I later realised (perhaps I should have realised at the start, but hey) was that order is important.  The MVC bundler doesn’t care about order, so there’s a big problem here.  After switching on bundling, I went from 0 runtime errors to at least 20.  There are two approaches I could have taken to resolve the problem;

  1. Create two separate bundles, one for base classes, the other for derived classes (I don’t care for this)
  2. Create a custom orderer and use naming conventions (prefix base class files with the name “Base”) to ensure order.

I went for the latter option.  This involved having to rename all my base class files and interfaces (granted interfaces don’t actually generate any JavaScript, but I wanted to keep the naming consistent) and writing a custom convention based orderer.  Neither of these things were challenging, just time consuming.

 

TypeScript is inconsistent

I can only speak from my own experiences here.  I don’t claim to be a TypeScript or JavaScript master, I’m just a normal developer as experienced as anybody else.

I love the strongly typed nature of TypeScript, that’s the feature that appeals most to me.  I do however have the following qualms;

 

TypeScript does not force you to use the language features of TypeScript

This is either a good thing, or a bad thing.  I can’t decide.  To be honest, I wish TypeScript did force you to use its own paradigm.  You can easily write pure JavaScript inside a TypeScript file and it will all compile and “just work”.  This is a bit of a downfall for me because I’ve always found JavaScript to be frustrating at best (can you think of an application you’ve written in JavaScript that hasn’t eventually descended into mayhem?).

What I mean is this, I can create a local variable and assign it a type of Element;

var element : Element = angular.element('.myelement')

The type constraint is redundant, and ReSharper makes a song and dance about the fact and basically forces you to get rid of it (yeah, I know I could turn this off but at the end of the day ReSharper is right).  I can assign function parameters type declarations, but I don’t have to.  (I did eventually go back in fill these in where I could).  I know that I should use type declarations and to be honest I wish I did use this feature more, but I’m lazy.  Next time I’ll be sure to do this from the start as I think it adds further structure to the code.

 

TypeScript doesn’t know it all

The project I was developing was built in conjunction with AngularJS.  I’ve had an up-down relationship with AngularJS to say the least, but I decided to fully embrace it this time and not switch between jQuery and Angular (yeah I’m aware that Angular uses jQuery lite under the hood, I’m referring to not switching between using $() and angular.element()).  I made heavy use of Angular Scope and I often had a dozen or more child scopes running on any one page.  So as a result, I had lots of code that looked roughly like this;

var scope = angular.element('.myselector').first().children('.mychildren').scope()

That’s perfectly valid code.  Even though I have already added the appropriate type definition files and referenced appropriate at the top of the file, TypeScript still insists that scope() is not valid in this context and I get a compilation error.  So I’d have to exploit the dynamic functionality of JavaScript to get around this;

var children = angular.element('.myselector').first().children('.mychildren');
var scope = children.scope();

Ok its not a big deal.  The scope variable is now of type any, so there’s no IntelliSense and no compile time checking.  But hey, wait, isn’t that the main point of using TypeScript in the first place?  Now if I pass scope to another function, I’ll exacerbate the problem (due to the fact that the parameter will have to be of type any) and before you know it, I’m just writing JavaScript again.  Fail.

Positive note

I’ve ranted about what I don’t like about TypeScript, and the frustrations I’ve encountered so far, but honestly I can’t sign its praises enough.  I estimate that so far TypeScript has saved me at least 3 million hours of effort.  Ok, perhaps a slight exaggeration, but you get the point.  Writing TypeScript is easy and familiar because I am comfortable with JavaScript and strongly typed languages such as C#.  I did spend perhaps a few hours reading the documentation and experimenting in the excellent TypeScript playground (both of which are excellent by the way), but generally thanks to previous experience with the aforementioned languages, I found that I “just know” TypeScript and it has a very smooth learning curve.

 

Summary

TypeScript is awesome, there is no doubt in my mind about that.  TypeScript saves all the pain that naturally comes with JavaScript and its only going to get better over time.   The tooling issues and inconsistencies are relatively insignificant, once you get used to them.