Starting With Angular 2 Development




If you just started with Angular 2 as I do and somewhat you also new in Javascript stacks, I'm sure we're all confused about which approach that is more suitable for our project. After trying all (Yeoman) generators for Angular 2 from different developers, most of their stacks is almost suitable to my requirement, but unfortunately not 100% fit in. 😁

So what is my requirement?

  1. Initially I want to have full-stack application, but I finally decided that I want to separate Frontend and API project.
  2. I will host this application on Azure Web App Service and because this is a managed service, I don't need to deal with setup the environment for deployment, no need to setup dedicated VM, just focus on development.

Where do I start?


For API project I don't really mind whether I should use Node.js or ASP.NET Core. But again, since I don't want to write everything from scratch, so I end up using LoopBack. LoopBack is more than sufficient to my scenario. So for the API part... it's settled.

And here's come the troublesome part, The Frontend part that using Angular 2. 😁

I've been using Angular 2 for couples of months now and in general, I'm pretty much like it. It was not the same impression I had when I was trying Angular 1. I like it because it feels familiar for those who already using Handlebars.js and TypeScript.


Forget the Generator!


Even though some of them gives you option to choose which stacks that you want to include in your project, but again, it feels like they put a lot of things inside whether you like it or not. So I recommend you to use angular-cli to generate your project. Wait, did I just read "generate"? Isn't just another generator? Well, at least it's official, meaning, whatever they put it there, it's their recommended best practice.

Here's some of my struggle before I discover angular-cli. Should I use Grunt or gulp? Should I use systemjs or webpack? Should I use TypeScript or Babel? This is all just matter of preference and angular-cli also comes up with their own "preference". But the difference is, this is come from them as in "officially" recommended. 😊

To create Angular 2 project using angular-cli simply use this command:

ng new PROJECT_NAME
cd PROJECT_NAME
ng serve

I'm using --style=scss options when creating this project since I want to use SCSS. More details about the command on this link: https://github.com/angular/angular-cli

Azure Web App Service Deployment


This is another pain in the *ss process, not because it's hard, it's because it takes time to figure it out the best practise to deploy our Angular 2 (generated by angular-cli) project to Azure.

I tested to wrap it on ASP.NET Core Application, but the continuous deployment process took longer time to satisfied dependencies for both stacks (Node.js and ASP.NET Core). This practise works when you're deploying your application through Visual Studio IDE. Because all dependencies already satisfied in your development machine, and what you need to do it's just publishing the project.

After spending two days of research and trial, I found out that the most convenient approach is to serve Angular 2 project using Express. Hold on, why would I serve my Angular 2 project using another "server". Can I just use "ng serve"? Node application on Azure Web App Service is running on IIS and your application main entrance is server.js from your node-express app. The scenario would be different if you host your app in your own VM.

Let's See The Recipe


To work with my scenario, I need to configure my project as follow:

Generate Custom Deployment Script

Generate custom deployment script using azure-cli. Specifically for Node.js deployment, run this comment on your project root:

$ azure site deploymentscript --node

This command will generate two files: .deployment and deployment.sh (or deployment.cmd). We can ignore the first file, but we need to edit deployment.sh (or deployment.cmd) to include this line just after this line:

eval $NPM_CMD install --production

So the codes become:

eval $NPM_CMD install --production
eval $NPM_CMD run build:prod

build:prod is a script in package.json that is basically run angular-cli equivalent to: ng build -prod

Custom web.config

This is one of the most important thing when developing Node.js app as Azure Web App Service. For most of the cases, we don't need to create the custom web.config because KuduScript will generate default web.config for you based on default Node.js application template where the entry point to your application is the server.js file in your application project root. Here is what our custom web.config and server.js for Node.js application looks like:

web.config
<?xml version="1.0" encoding="utf-8"?>

<configuration>
  <system.webServer>
    <webSocket enabled="false" />
    <handlers>
      <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>

    <rewrite>
      <rules>
        <!-- Do not interfere with requests for node-inspector debugging -->
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^server.js\/debug[\/]?" />
        </rule>

        <!-- Consider whether the incoming URL matches a physical file in the /public folder -->
        <rule name="StaticContent">
          <action type="Rewrite" url="public{REQUEST_URI}"/>
        </rule>

        <!-- All other URLs are mapped to the node.js site entry point -->
        <rule name="DynamicContent">
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="server.js"/>
        </rule>
      </rules>
    </rewrite>

    <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin"/>
        </hiddenSegments>
      </requestFiltering>
    </security>

    <!-- Make sure error responses are left untouched -->
    <httpErrors existingResponse="PassThrough" />

  </system.webServer>
</configuration>

server.js
var express = require('express'),
    path = require('path'),
    fs = require('fs');

var app = express();
var staticRoot = __dirname + '/'; // this is you app root

app.set('port', (process.env.PORT || 3000));
app.use(express.static(staticRoot));
app.use(function(req, res, next){

    // if the request is not html then move along
    var accept = req.accepts('html', 'json', 'xml');
    if(accept !== 'html'){
        return next();
    }

    // if the request has a '.' assume that it's for a file, move along
    var ext = path.extname(req.path);
    if (ext !== ''){
        return next();
    }

    fs.createReadStream(staticRoot + 'index.html').pipe(res);
});

app.listen(app.get('port'), function() {
    console.log('app running on port', app.get('port'));
});

In my case I change the app root to '/wwwroot/' instead of '/'. If you are using angular-cli default output folder, you need to change this to '/dist/'. You can configure angular-cli output folder in angular-cli.json file.

Azure App Service - Application Settings


Last but not least, we need to configure Azure Application Settings. After few times trial, for my scenario, this configuration is the one that successfully deployed my application.


I use Python version 2.7 (required for node-sass and node-gyp) and although it's not relevant, I turned off PHP since I don't use it and I turned on Web sockets.


This is the most important of the configuration steps, make sure we didn't use old version of Node.js and in this case, I'm using version 6.5.0 to match my development machine.

For deployment process, I'm connecting my Visual Studio Team Services account to my Azure Account so everytime I have a git push to specific branch, the auto deployment will be triggered. If you guys interested to see how it's done, write on comments below ...

Happy Coding !!!
😎