Getting your Angular Router application actually working in a non-root folder on Internet Information Services

The Angular Router is a fantastic module for Single Page Apps. However, to deploy it in a Production scenario you will typically need to do some configuration to make it work. This article details the steps necessary to deploy an Angular Router application anywhere on Internet Information Services (IIS).

Here is a quick overview of what is covered in this article:

  1. Use the Angular Tour of Heroes as a sample Angular Router application.
  2. Install IIS with the URL Rewrite Module.
  3. Deploy Tour of Heroes to the web root in IIS.
  4. Deploy Tour of Heroes to a specific sub-folder in IIS using the base-href flag.
  5. Use a web.config file to leverage the Angular Router when deploying to a sub-folder in IIS.

Example: Tour of Heroes#

For a concrete example of the steps involved I will use the Angular Tour of Heroes tutorial application. You can download a complete version from the Introduction page. Extract it to a folder called toh.

Go to your toh folder and do an: npm install

Because we are deploying to IIS, I assume you probably also want this to work on Internet Explorer. So, you have a few extra steps here. You need to open the file: toh\src\polyfills.ts and un-comment all the imports in there. Note: in the comments there are some extra npm installs:

npm install --save classlist.js
npm install --save web-animations-js

Once this completes we can test our Tour of Heroes application in our development environment by running:

ng serve

Point your browser at:
http://localhost:4200
You should see the Tour of Heroes application in all its glory.

Tour of Heroes uses the Angular Router so you can click on Dashboard and Heroes and see the view change in the application. Notice that even though this is a Single Page App, the URL in the browser is getting updated to match our view. Refreshing, clicking the back button, and even copying and pasting a link directly into another tab all work because the Angular Router takes care of all the heavy lifting for us.

Setup Internet Information Services#

To mimic a Production Environment we will deploy our Tour of Heroes application to IIS so:

Simple Deployment#

Of course in production you won’t use ng serve, so let’s do a production build using:

ng build --prod

This builds your application and outputs it to your outDir defined in .angular-cli.json. By default this will be toh\dist.

You can take the contents of this folder and drop it into the root of your Web server and everything will work just fine. For example, on my system IIS is installed in C:\inetpub and hence the default web root is C:\inetpub\wwwroot. After building: deploy your application by copying the contents of your toh project’s dist folder into the wwwroot folder.

Point your browser at: http://localhost and you should see the Tour of Heroes dashboard again. Notice this time we don’t include the port in the URL because by default IIS runs on port 80.

That was easy! But, what if we want to deploy to a sub-folder in our Web Server?

Deploying into a Sub-folder#

Unfortunately, deploying an Angular Router app to a web folder other than the root requires a bit more effort.

To avoid confusion, remove all the files from your IIS wwwroot. Now let’s create a folder in our web root called toh. Mine looks like this: C:\inetpub\wwwroot\toh. Copy the contents of of your project’s toh\dist folder to your IIS wwwroot\toh folder.

Now if we try to use the Tour of Heroes application by going to http://localhost/toh/index.html we will get a 404 error in the console.

The base-href Flag#

In the Angular Deployment page it discusses the base tag. The base tag tells our Angular application where it will be deployed. Later in this article we will explore ways to make our deployments more flexible, but for now let’s build our Tour of Heroes application again. Except, this time we will use the
base-href flag to tell ng build that we will be deploying to the toh folder in our web server:

ng build --base-href "/toh/" --prod

When that completes, copy the contents of of your project’s toh\dist folder into your IIS wwwroot\toh folder. Now if you go to http://localhost/toh/index.html
you should see the application and be able to follow the router links by clicking on Dashboard and Heroes.

However, we aren’t home yet. If you try to refresh the page, by hitting F5 for example, you will get an error. That’s because our web server is getting Angular Router URLs that it isn’t set up to handle. So, we need to add some configuration that tells our web server how to fallback to our index.html page so the Angular Router can handle those URLs for us.

Server Configuration with web.config#

The configuration necessary is somewhat documented on the angular Deployments page in the Server Configuration section. Unfortunately, it is rather light on the details. We will go through step by step instructions to get this working.

In our project in toh\src we need to create a web.config file with the following content:

<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Angular Routes" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="./index.html" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

</configuration>

Note there isn’t anything specific to the Tour of Heroes application in there except that our main fallback file is index.html. So, this will work for any Angular application.

We want this to get included with our build so we can deploy it with our Tour of Heroes application. So, let’s add it to the assets in our project’s
.angular-cli.json file like this:

"assets": [
    "assets",
    "favicon.ico",
    "web.config"
],

Let’s build again:

ng build --base-href "/toh/" --prod

We verify that web.config is getting copied to our dist folder. Now deploy our application by copying the contents of dist to our IIS wwwroot\toh folder. In the browser go to http://localhost/toh/index.html

Now our Tour of Heroes application routes correctly and we can refresh. Also, if we copy a URL and paste it into another browser window it works just fine. So, we can see that our Angular Router application is supporting deep links like we intended.

Summary#

The Angular Router is a powerful library for enabling Single Page Apps. Deploying applications to the web root is trivial. With some configuration we can additionally support flexible deployments to anywhere in our IIS web server.