How to Host an AngularJS Site on AWS S3


AngularJS is a Javascript Framework that allows you to create dynamic front-end web applications easily.

I have traditionally packaged these applications through NodeJS, and Grunt (or Gulp) in particular.

Once it needs to be hosted for the whole world to see, I always used to push the static folder up to an Apache2 or Nginx Linux web server.

There’s really not a massive need for this though, as it’s easily possible to AngularJS applications completely serverless using a combination of AWS S3 and Cloudflare.

You don’t have to use Cloudflare in your own setup, and could technically keep everything within AWS by swapping Cloudflare out with Route53.

But I really like Cloudflare and have used it for many years wherever I get a chance to.

Quickstart

You will need an AWS account, and possibly a Cloudflare account too if you want to use them for your domain and DNS management.

To host an AngularJS website on S3 you will need to follow these general steps:

  • Create an S3 bucket with the name of the domain you will expose
  • Set the bucket to public
  • Update the HTML5Mode and HashPrefix in your AngularJS code
  • Package and upload your AngularJS site to the S3 bucket
  • Update the bucket for ‘Static website hosting'
  • Update the ‘Redirection rules'
  • Update your DNS to point to the S3 bucket

The problem

So doing most of the above would probably seem obvious.

However, when you have canonical/permanent HTML5 URLs (such as <a href="https://analytics.statvoo.com/developers" target="_blank" rel="noreferrer noopener">https://analytics.statvoo.com/developers</a> or <a href="https://analytics.statvoo.com/plans" target="_blank" rel="noreferrer noopener">https://analytics.statvoo.com/plans</a>, then navigating to them and refreshing the browser will result in either a 404 or 403 error page served by S3.

If you were hosting this yourself, you could fix the problem by serving your app through npm or updating your .htaccess file to enable mod_rewrite capabilities.

S3 has none of this.

This is where you need to revert to having a backup hashPrefix and S3 Redirection rules to counter it.

Luckily, it’s really easy. So let’s do it now!

Update your AngularJS Application

In your AngularJS app, find (or add…) the $locationProvider... code as below:

angular.module(app, [])
  .config(function($locationProvider) {
    $locationProvider.html5Mode(true).hashPrefix('!');  
  });

Remember to update your app name if required, and any other weird things you may have changed beforehand.

How to setup S3 for static AngularJS serving

We are going to create a new S3 bucket for our site, which was analytics.ataiva.com.

Go S3 and create a new bucket called analytics.ataiva.com, remember to change it to your own domain/subdomain.

Make sure that you deselect “Block public…” and make the bucket “public”.

Now upload all your static AngularJS site assets, HTML and everything else that your packager (Grunt?) created for you.

Once this is done, select Properties and open the Static website hosting box.

At this point you can select “Use this bucket to host a website”, enter index.html into the “index document field” and then update the Redirection rules field with the following:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>analytics.ataiva.com</HostName>
      <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>analytics.ataiva.com</HostName>
      <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

Make sure to update your own HostName in both sections to whatever you named your bucket, which should also match your domain/subdomain hostname.

The properties box should look something like this:

Make sure to Save this and then it’s time to update the DNS entry.

Update your DNS

Head over to your DNS for the specific domain property and add (or update…) a CNAME record, this should be the subdomain or the first section of your bucket name. In my case, it will be analytics.

Now set the target to <bucket-name>.s3-website-eu-west-1.amazonaws.com, in my case it would be analytics.ataiva.com.s3-website-eu-west-1.amazonaws.com.

Now you’re good to go!

Wait a moment and then head over to your website in a browser, click between links and then try and refresh.

Job done!