0 - 60 with Angular 2 & Visual Studio - Part 2

UPDATE - June 2, 2016

I gave a talk on this topic for the AngularMN meetup in June, and to support that I created a new repository with the the recorded talk, the organized code and links to a couple references. Please check it out. Thanks!

https://github.com/sstorie/presentation-0-60-with-angular2-and-visual-studio

Now back to the original article...

This is the second part of a two-part series on writing Angular 2 code with Visual Studio. In this part we're not going to dive into the Angular 2 code itself, but rather talk about what the experience of building it in Visual Studio is like, and some things to watch for. For reference, I'm using Visual Studio 2015 Update 2 and ASP.NET 4.5 (i.e., not the bleeding edge ASP.NET Core stuff).

In the first part we walked through building the back-end API, and structuring the app to support serving our Angular application. Let's continue now and explore what building the client-side of things is like.

Decisions to make

When using Visual Studio for any typescript-based project (be it Angular 2 or something else) you need to consider a couple things because Visual Studio can do a lot for you:

  • Do you want Visual Studio to manage your NPM packages?
  • Do you want to have Visual Studio compile your typescript for you? Or would you rather use something like webpack?
  • Do you want to use the built-in task runner to manage NPM tasks?

Personally, I think it's a hold-over from how Microsoft used to present VS as an all-in-one tool for development, but you'll need to think about the questions above. Let's take each of these one-by-one.

Managing NPM packages

Visual Studio 2015 has built-in support for package.json. This means it provides intelli-sense for all kinds of good stuff while editing the file:

When you make and save updates to the file VS will automatically start downloading the packages changed. This can be handy for very small projects, but I actually prefer to handle this myself using the console. I think it makes errors easier to see, and helps me understand what's happening.

Now, the pain of this is that you can't just tell VS to never restore npm packages automatically without disabling all npm related functionality (including the task runner integration discussed below). I've had experience with VS making my machine crawl because it kicked off many nodejs processes trying to keep the packages in sync with package.json. It seems to have gotten a little better with VS 2015 Update 2, but if you want to completely disable npm integration you can follow the guidance of this StackOverflow post.

Compiling typescript

By default VS will compile your typescript code automatically whenever you build the project the files are associated with. Depending on your environment, or if you have a simple "website" project, this could be a very useful thing. With something more complex like an Angular2 application this could be a waste of time. How typescript files are handled is controlled by the tsconfig.json file present in your folder structure (quick link to the complete schema).

My personal preference is to defer the compilation of typescript files to something like webpack so I can do more advanced processing. In that case I usually update tsconfig.json to include the following:

{
  ...other stuff...
  "compileOnSave": false,
}

Now even with this you'll still find that Visual Studio will compile the typescript files when you build the project, so update that we need to do a more invasive change. What we need to do is update the .csproj file to include a tag that tells Visual Studio to not compile typescript files at all. To make this update we first unload the project from the solution like so:

animated gif showing how to unload the project

...and once that's done we can edit the raw file and add the following tag to the first property group:

    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>

Once you've done that VS will completely ignore the ts files when you build the project. So add that tag, save the .csproj file, and you can reload the project:

animated gif showing the reload

How to execute NPM tasks

I think in the years after Visual Studio 2013 was released Microsoft was playing catch-up with the explosion of automated javascript build pipelines using Grunt and Gulp. Mads Kristensen (of Microsoft) came up with a solution, and built something called the Task Runner Extension that would automatically detect the respective config files and let you run tasks from the GUI. Here's an example of how it looks with a grunt file:

This extension brought the experience of managing these task runners a little closer to home for VS users, but it also let you integrate the tasks into the build pipeline of VS itself. So for example, you could say that a specific gulp task should run when I build the entire .NET project. Useful stuff.

Now, Mads is a seriously prolific developer, and he eventually added the ability to manage NPM tasks within the Task Runner as well. Here's an example shot of running an npm build task within VS:

Now, that said there is one big gotcha you need to be careful of. VS ships with a specific version of node it will use when running tasks by default. If you happen to install a newer version on your system, and install packages using it, then some of the npm commands may not work. For example, I'm using node-sass in this code but by default it's not working right when I build via the task runner:

To fix this we need to tell VS that we've got a newer version of Node it should use (there's Mads yet again!). We can do this pretty easily using VS's option dialog:

So what do I do?

I personally like to manage these items myself from the command line. I'll fire up ConEmu and run my npm tasks on a different monitor so they're out of the way. But it's important to understand what options you have should you prefer something else.

Writing Angular 2 code

Okay, with these decisions made we can actually start writing some Angular 2 code. I won't spend a lot of time elaborating the code here because it's pretty standard, and has nothing specific to Visual Studio. However, I will highlight how you might consider structuring your application to take advantage of what VS has to offer.

What we're going to build is a simple app to query the API we built in the previous post. We can enter the zip code we're interested in, and once the API call is complete we are presented with a simple chart showing the historical temperatures. It looks like this:

So, nothing crazy, but arguably somewhat useful...maybe :) Now I'm not saying this Angular code is amazing...in fact it's not, but you can see all of it in my github repo:

https://github.com/sstorie/experiments/tree/master/0-60-with-angular2-and-visual-studio/source

Considerations to make

VS has solid typescript support right out of the box, but there are some things to be aware of while building Angular 2 apps. Here's a list I have run into:

  • The importance of tsconfig.json
  • Whether to use inline templates/CSS or use external files for your components
  • How to approach editing files while debugging the website within VS
  • Using webpack to create easy bundles to serve with Nancy

Let's take each of these in turn.

The importance of tsconfig.json

As I said earlier, VS uses this file to know how to process the typescript files it finds. For example, it's absolutely critical that you include the following lines in your tsconfig.json, otherwise your Angular 2 code will compile, but likely fail when running in a browser:

In the image above you can also see I'm specifying the files I want this config file to apply to. By including the root file of my project (i.e., the one that ultimately imports all the others) I can apply this config to how VS treats all my project's files. So for example, if I start editing a new service, that has yet to be imported by a file in my project, VS will throw errors like this:

This is because I haven't told VS how to treat this specific typescript file. Once I import this service into a file that is already managed by the config, then the error goes away. If you're not aware of this, then it might seem really confusing why a bunch of errors are thrown when you create new Angular 2 components.

Of course, you can update tsconfig.json to include all typescript files too, but that depends on your specific application.

Whether to inline templates/CSS or use external files

With Angular 2 you can either include the template for a component as a string right in the component's file itself, or refer to an external html file. I'm a little torn on this one actually because I really like having the HTML right in the same file, but first-class support for that just isn't in the editors yet...VS included. However, if you are okay with moving the HTML to an external file, then you can use the great built in support for editing HTML files.

The same thing applies to your component styles. Angular 2 provides some really awesome ways to scope your CSS to a specific component through View Encapsulation. If you haven't seen it yet, check out Justin Schwartzenberger's great talk at ng-conf 2016. However, out of the box this requires you to write your CSS right in the component file...preventing the use of tools like sass and postcss. With some webpack loaders however, you can move these styles to an external file and still include them. This means you can use the support VS has for CSS and sass files (including intelli-sense):

Editing files while debugging the site

In this example application you can run the project, which will start up IISExpress to host the site and allow us to break into the server-side code. So we can set a breakpoint within our API, and still use a browser to debug the client side. If you're running something like webpack --watch in a console, then you can even edit your html and typescript files while the solution is running.

The problem with VS though is that once you're running the application VS will allow you to add some types of files, but no new folders, and once you add a file you can't delete it.

So while you're actively developing the project this can be frustrating. If I'm creating new components I'll usually try to create the folder structures and empty files in advanced of a debugging session so I get around this.

Using webpack to create bundles

This isn't really too specific to VS, but I just wanted to call out that webpack is a great tool for creating a complete bundle for your app that can be easily served by something like Nancy. The reason I don't use much of the built-in support VS offers for typescript is because webpack is so much more powerful. There are insanely complicated webpack files out there, but you really don't need much to do some powerful things:

var autoprefixer = require("autoprefixer");

module.exports = {  
    // Define the entry points for our application so webpack knows what to 
    //  use as inputs
    //
    entry: {
        app: ["./App/main"]
    },

    // Define where the resulting file should go
    //
    output: {
        filename: "content/[name].bundle.js"
    },

    resolve: {
        extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },

    // Turn on source maps for all applicable files.
    //
    devtool: "source-map",

    module: {
        loaders: [
            // Process any typescript or typescript-jsx files using the ts-loader
            //
            {
                test: /\.tsx?$/,
                loaders: ["ts-loader"]
            },

            // Process Sass files using the sass-loader first, and then with the 
            //  raw-loader so we can inject them into the 'styles' property of
            //  components (to take advantage of view encapsulation)
            //
            {
                test: /\.scss$/,
                exclude: /node_modules/,
                loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] // sass-loader not scss-loader
            },

            // Load any HTML files into raw strings so they can be included with
            //  the angular components in-line
            //
            {
                test: /\.html$/,
                loaders: ['html-loader']
            }
        ]
    },
    postcss: function () {
        return [autoprefixer];
    }
}

Wrapping up

So in this post I didn't go through the specifics of the Angular 2 code, but I explained some of the things you might encounter when building Angular 2 apps with Visual Studio. It's an amazingly powerful IDE, and if you're a .NET dev don't think you can't build Angular 2 apps with the tools you know.

All of the code for this example is available in my github repo.

Thanks for reading!

comments powered by Disqus