Setting up a TypeScript – RequireJS – MVC 6 web app in VS2015

Setting up a new Web Project in Visual Studio 2015 is easy!
Setting up a project and making TypeScript and RequireJS work together – not all that easy.
Hopefully this step-by-step guide will help you get up to speed quickly. We’re taking it from an empty web project to setting up MVC 6, TypeScript compilation with Gulp, retrieving definition files and finishing off with a module load with RequireJS.

Disclaimer: Please note that this article was written using Visual Studio Enterprise 2015 RC using the beta-4 bits. So if you are using a different version, some of the information in this article will not be accurate.

1. Creating a new Web Project

Open Visual Studio and:

  • File-New-Project (Ctrl-Shift-N)
  • Select ASP.NET Web Application
  • Under ASP.NET Preview Templates select Empty

2. Add MVC to the project

First we need to add two more packages to the solution. Add the following to the dependencies section of project.json:

    "Microsoft.AspNet.Mvc": "6.0.0-beta4",
    "Microsoft.AspNet.StaticFiles": "1.0.0-beta4"

No we need to add some code to Startup.cs:

   public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });
            });
        }
    }

If you are unfamiliar with ASP.Net 5, we’ve just enabled MVC, enabled use of static files and setup a route handler for incoming requests.

Setup of the MVC parts

Add a folder to the project root named Controllers and one named Views. Inside the Views folder, add a folder named Home.
Add a HomeController.cs file to the Home folder, add the following code:

using Microsoft.AspNet.Mvc;
namespace TS_require_Web.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Add a cshtml file named Index.cshtml to the Home folder and add some html markup, like for ex:

<!DOCTYPE html>
<html>
<head>
    <title>TypeScript Module loading with RequireJS</title>
</head>
<body>

<h1>Setup project</h1>

</body>
</html>

Given everything is setup correctly now, it should be possible to run the project using the web command or with IIS Express.

3. Adding NPM packages

Now we need to add a a new file to retrieve some NPM packages needed. In the the project root create a file named: package.json (Ctrl-Shift-A -> NPM configuration file)
Open the file and under devDependencies add references to some needed packages, making the devDependencies section look like the following:

"devDependencies": {
    "gulp": "^3.9.0",
    "rimraf": "^2.4.0",
    "gulp-typescript": "^2.7.6",
    "gulp-sourcemaps": "^1.5.2",
    "merge": "^1.2.0",
    "requirejs": "^2.1.18"
  }

In the Visual Studio solution expand the Dependencies node and make sure all packages are marked as installed (by showing a version number). If they aren’t – right click the NPM node and select “Restore Packages”.

4. Adding a Gulp file

Position in the projects root in solution explorer, press Ctrl-Shift-A and select “Gulp Configuration file”.
In the gulpfile, require in the following packages rimraf, gulp-typescript, merge, and fs.

Then we need to add a few gulp-tasks and configurations. For the TypeScript compilation we need to define a TypeScript Project Setting, some paths, a compile task and preferably also a watch task. Watch tasks enables automatic compilation of the TS files triggered by a save, something that makes the workflow much faster when iterating over small code changes.

The Gulpfile.js should look like follows:

var gulp = require('gulp'),
    rimraf = require('rimraf'),
    ts = require('gulp-typescript'),
    merge = require('merge'),
    fs = require("fs");

eval("var project = " + fs.readFileSync("./project.json"));

var paths = {
    npm: './node_modules/',
    lib: "./" + project.webroot + "/lib/",
    tsSource: './TypeScript/app/**/*.ts',
    tsOutput: "./" + project.webroot + '/scripts/app/',
    tsDef: "./TypeScript/definitions/"
};

gulp.task("clean", function (cb) {
    rimraf(paths.tsOutput, cb);
});

var tsProject = ts.createProject({
    declarationFiles: true,
    noExternalResolve: false,
    module: 'AMD',
    removeComments: true
});

gulp.task('ts-compile', function () {
    var tsResult = gulp.src(paths.tsSource)
					.pipe(ts(tsProject));

    return merge([
		tsResult.dts.pipe(gulp.dest(paths.tsDef)),
		tsResult.js.pipe(gulp.dest(paths.tsOutput))
    ]);
});

gulp.task('watch', ['ts-compile'], function () {
    gulp.watch(paths.tsDef, ['ts-compile']);
});

gulp.task("copy", function () {
    var npm = {
        "requirejs": "requirejs/require.js"
    }

    for (var destinationDir in npm) {
        gulp.src(paths.npm + npm[destinationDir])
          .pipe(gulp.dest(paths.lib + destinationDir));
    }
});

5. Prepare script folders

Under wwwroot create two folders, one named lib and one named scripts.
Under the scripts folder, create a new folder named app.
Test to make sure the gulp copy-task is setup correct by running it from for ex Task Runner Explorer. After it’s executed and no errors occurred, check to see if a new folder containing the require.js file has been copied to the lib folder.

6. Add TypeScript folders

Create a new folder in the project root named TypeScript, under that create three new folders named: app, definitions and extdefinitions.
The plan here is to keep all code that will be written to contain app logic in the app folder. The TypeScript compiler will output definition files for your code and put those in the definitions folder. And then there is the extdefinitions folder that will hold all the definition files that you have downloaded, imported or maybe written but are for code that you are not responsible for.

Now – finally time to add some TypeScript files!

7. Add TypeScript files to setup RequireJS

Alert box saying Configure TypeScript Compilation
We need two TypeScript files, one named config.ts and one named main.ts, both under the TypeScript/app folder. (Position on the TypeScript/app folder and Ctrl-Shift-A as usual, but if you can’t see the TypeScript file type, expand the ASP.NET 5 tree node in the left hand column and select ASP.NET 5 Preview, this show the TypeScript File and it should be close to the JavaScript File)
When creating the first TS file, a popup will show, reminding you that you have to configure compilation with a task runner like Gulp or Grunt and offer to show instructions, just click “No” to continue.

config.ts

/// <reference path="../extdefinitions/tsd.d.ts" />
require.config({
    baseUrl: 'scripts/app',
    paths: {},
    shim: {}
});

// load AMD module main.ts (compiled to main.js)
require(['main'],(main) => {
    var app = new main();
    app.run();
});

main.ts

class Main {
    runString: string;

    constructor() {
        this.runString = 'hello from main';
    }

    run() {
        alert(this.runString);
    }
}
export = Main;

But there’s squiggly’s under ‘require‘ in config.ts, to remedy this we need a definition file for RequireJS.

8. Get a definition file for RequireJSAn image showing the Package Manager Console

There is a great project on GitHub named DefinitelyTyped. This project contains loads of definition files for different JavaScript libs and frameworks, see more info at definitelytyped.org. The easiest way to work with them is to install TSD – the TypeScript Definition Manager.

To install TSD, run

npm install tsd -g

from the Package Manager Console.
In Package Manager Console, navigate to the root of the project and run:

tsd init

Edit the ‘tsd.json’ file that init generated. Set path and bundle to our previously defined paths.

{
  "version": "v4",
  "repo": "borisyankov/DefinitelyTyped",
  "ref": "master",
  "path": "TypeScript/extdefinitions",
  "bundle": "TypeScript/extdefinitions/tsd.d.ts",
  "installed": {}
}

After it’s been installed it’s time to use it to get the definition file for RequireJS.
From the Package Manager Console (positioned in the root of the project) run:

tsd install require --save

This will now install the definition file for RequireJS and also add a reference to the ‘tsd.d.ts’ file. Now the easiest way way to reference the definition files in your project becomes a single use of the tsd.d.ts file. So to see the squiggly’s disappear and remove any compilation errors, just add this line above all code in the config.ts file:

/// <reference path="../extdefinitions/tsd.d.ts" />

9. Reference RequireJS and make it work

In the Index.cshtml file created when setting up the MVC parts, add a script to reference and init RequireJs. In the Head-tag add the following:

<script data-main="scripts/app/config.js" type="text/javascript" src="~/lib/requirejs/require.js"></script>

Make sure all your TypeScript files are compiled, and run the app via the web command or IIS Express.
You should now get an alert box from the browser of your choice saying “hello from main”!hello from main
So, that’s the main.ts code being executed sending it’s message out to the world.
The end result of all this is subtle, but it’s hopefully a solid base to build upon when creating a larger application.

All code can be found in my GitHub repository.

Protip

1. Try to keep all generated .js files in one folder, this way you can empty it and recompile in case anything get’s fudged (setup a clean task for the folder).
2. It’s ok to have static .js files in a project. Some developers in your team might not be comfortable with TS. Just try and keep their .js files separated from generated files.
3. If some team members insist on only using JavaScript, you can create definition files for those files, making it easier to work with them for you from TS.
4. If you need to use external js libraries, TSD is your friend!

 

Happy coding! 🙂

Setting up a TypeScript – RequireJS – Gulp – MVC 6 Web Project in Visual Studio 2015 RC
Tagged on:                 

10 thoughts on “Setting up a TypeScript – RequireJS – Gulp – MVC 6 Web Project in Visual Studio 2015 RC

Leave a Reply

Your email address will not be published. Required fields are marked *