Angular 6 application hosted on Azure Storage Static website

A few days ago Microsoft announced a new public preview feature for Azure Storage called Static website. It enables you to host a static web app using Azure Storage which is multiple times cheaper than a traditional required Web App. Reason enough to give it a try.

Create a Storage account

To use the Static website feature we need a general-purpose V2 Storage Account. You can either manually create the resource within the Azure Portal or by using the following ARM Template:

Enable Static website feature

Unfortunately, we can’t enable the Static website feature using an ARM Template (thanks to Gaurav Mantri) because it is not part of the Storage Resource Provider API. So we have to manually enable it after we’ve provisioned the Storage Account.

We can do that within our previous created Storage Account: Select Static website (preview) to configure a container for static website hosting:

enablestaticwebsite

Since our example application will have an index.html,  we can leave the index document name field as it is.

Note: If you have to automate this process, it is still possible to enable this feature using the Azure Storage Services REST API.

After we save our changes we get the primary endpoint URL of our site:

spaurl.png

Create an Angular Single Page Application

We use the Angular CLI to scaffold an Angular sample application that already has routing enabled. The name of our app will be spastore: 

ng new spastore --routing

 We also create a new component named subcomponent to demonstrate the routing capability:

ng g component subcomponent

And configure the routing module accordingly:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SubcomponentComponent } from './subcomponent/subcomponent.component';

const routes: Routes = [
    { path: 'subcomponent', component: SubcomponentComponent },
];

@NgModule({
    imports: [RouterModule.forRoot(routes, { useHash: true })],
    exports: [RouterModule]
})
export class AppRoutingModule { }

Note that we use the HashLocationStrategy as opposed to the default PathLocationStrategy because the later will result in 404 errors. This is because we can’t define a rewrite URL for our static website and Azure will try to resolve the specified resource – e. g.:
https://spastore.z6.web.core.windows.net/subcomponent

The HashLocationStrategy represents its state in the hash fragment of the browser’s URL. So this will be the new route for our subcomponent:
https://spastore.z6.web.core.windows.net/#/subcomponent

Finally, we add the router outlet to the app.component.html which displays our component and add a router link:

<nav>
  <a routerLink="/subcomponent">Subcomponent</a>
</nav>
<router-outlet></router-outlet>

Now it’s time to compile the application and get a production build. Once again we use the Angular CLI:

ng build --prod

The build artifacts are stored within the dist folder and are ready to publish. We can do that by clicking on the $web link within the Static website (preview) blade. Then we have to click on the Upload button and select all files within the artifact (dist) folder:

angularupload

If we browse to the URL we can see our Angular App up and running and also the routing is working as expected:

angulardemo.png

You can test the site here: https://spastore.z6.web.core.windows.net

The source code including the ARM Template and the Angular sample application can be found in my GitHub repository.

Update:

You can use the PathLocationStrategy by setting the error page to index.html (thanks to @nthonyChu). The first try to serve a URL like https://spastore.z6.web.core.windows.net/subcomponent will fail since it is not a valid resource. Then the path will get passed to the error page which is our index.html (page returns content with 404 status code). However, this is a hack. I still recommend using the HashLocationStrategy until a rewrite mechanism is in place.