# January 8th, 2020

# Conversion to a Static Site with VuePress and AWS S3

I've been working a lot lately with AWS and I figured it was high time that I leveraged some of that newfound kowledge to improve my own website. I set out with 3 goals in mind:

  1. Reduce my monthly AWS bill
  2. Improve performance
  3. Create a better experience for both the user as well as the developer (me 😄)

First is to address my current cost of operating a site which is quite simple in scope. As of last November, I'm clearly paying too much considering other hosting options for a personal résumé and blog.

Cost Reports November

I had originally chosen to implement ethanaa.com as a Spring Boot / Angular.js application and serve it using AWS Elastic Beanstalk. This suited my needs because I had initially planned on adding more interesting server side code (users, authentication, apis, etc.) to the app, but alas I never did. So it's time to bring the site into better alignment with its newly solidified purpose: an easy to maintain and performance optimized personal web profile.

With the cost benefits in mind, I decided to try my hand at a static site conversion so that I could serve the whole website out of an S3 bucket.

According to Amazon the total cost of hosting your site in this fashion will be $1-3/month. Looking at the S3 pricing seems to confirm that assertion for my case.

  • GET Requests cost $0.004 per 10,000 requests
  • Data Transfer Out costs $0.090 per GB (up to 10 TB / month)

Sounds good to me 👌. Let's get started!

# VuePress

VuePress

Of all the modern JavaScript frameworks available, I am most experienced with Vue.js. I looked at some options and ultimately chose VuePress as my static site generator.

VuePress allows me to theme the site using the familiar Vue.js and generate pre-rendered static HTML which is performant and SEO friendly. It also provides a number of excellent plugins, which means less code for me to write in order to deliver the experience that I'm after.

Including...

Editing content on the site is greatly simplified by a build step which compiles Markdown files (which allow embedded Vue usage) into HTML.

Building is as simple as yarn docs:build

# Amazon S3

S3

The first step to using S3 is to create a bucket. I named it after my domain name (with the www subdomain) specifically to make DNS resolution work properly with GoDaddy, but since migrating to using CloudFront and Route53 I no longer believe this to be a requirement.

S3 Bucket

The root of the bucket will contain the files output by yarn docs:build. They can be found in the docs/.vuepress/dist directory.

Next is to enable static website hosting. The index document should be index.html and the error document can be set if you have one.

S3 Static Website Hosting

Now turn off "Block all public access" in the Permissions tab and add the below Bucket Policy and CORS Configuration.

S3 Public Access

# Bucket Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::www.ethanaa.com/*"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12

# CORS Configuration

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Content-Length</AllowedHeader>
</CORSRule>
</CORSConfiguration>
1
2
3
4
5
6
7
8
9
10

This CORS config exists primarily to allow the Content-Length header to be passed to CloudFront so that it will perform compression.

# Amazon Certificate Manager

Certificate Manager

ACM will provide us a free public certificate for our domain name so that we can use HTTPS.

Make sure to request a certificate which covers all required subdomains i.e. ethanaa.com as well as www.ethanaa.com.

I used DNS validation and the process of adding the CNAME records was straight forward with both GoDaddy and subsequently, Route53.

# Amazon CloudFront

CloudFront

CloudFront acts as the content delivery network (CDN) so that the site retains performance no matter where in the world its being accessed from. It also has the added benefit of DDoS mitigation.

Create a distribution. The "Origin Domain Name" should be copied from the S3 bucket's static website hosting configuration. The desired URL is labeled "Endpoint".

Redirect HTTP to HTTPS, configure TTL, "Compress Objects Automatically", choose "Custom SSL Certificate" and select the previously created public certificate.

# Amazon Route53

Route53

Route53 is used as the Domain Name System (DNS). Domain name subscriptions often come with DNS capabilities, but due to the limitations I experienced with GoDaddy (can only point an A record at an IP address) Route53 was the obvious choice. It's integrated into AWS and you can point an A record to a CloudFront distribution.

  • Create an A record with an alias targeting the CloudFront domain name.
  • Create a CNAME record with the name www and value ethanaa.com.

Given some time for all of changes to propogate, the new static site is now available over HTTPS with a valid certificate (both at the naked domain and the www subdomain) and HTTP requests are automatically upgraded to HTTPS.

Mobile Google PageSpeed Insights

Google PageSpeed Insights confirms excellent mobile and desktop performance with consistent scores in the high 90s for mobile and often 100 for desktop.

Desktop Google PageSpeed Insights

Updates to come when I find out how much it's costing me! 💵

Edit

Update 02-01-2020: January is over and I have some first monthly cost data to share.

Last Updated: 2/10/2020, 3:35:56 AM