How many AWS services do you need to host a static webpage? (1/2)

Mateusz (mat3e)
Feb 4 · 6 min read
Photo by Dallas Reedy on Unsplash

The public cloud is just happening. Period.

I knew some of AWS/Azure/GCP services by their names and functions, but I really wanted to gain hands-on experience in using them.

As with (probably) most programmers, I created a couple of webpages one of which was for a member of my family. I’m ashamed of what it looks like now, but I still maintain it. Recently, I had to change its hosting, so… I decided to use AWS! To do what was needed and to achieve what I wanted.

JS modifications

First things first, let’s start with a JS code. The webpage was almost 100% static, with a visitor counter. PHP script was using a text file to store the number of visitors and to increment it. What’s worse, there were HTML frames to get around the problem of calculating visits after refreshing the page.

I’ve almost never used Vue, so it was a natural choice. I created 2 components in the index.html:

  1. For the main context of the webpage
  2. For the “intro”, disappearing after the first click:
const Intro = {
data: function () {
return {
shouldHide: !!sessionStorage.getItem('shouldHide')
}
},
template: '<div v-if="!shouldHide" @click="startPage" style="(...)"><img src="img/bg.jpg" style="(...)"></div>',
methods: {
startPage: function () {
const vm = this;
vm.shouldHide = true;
sessionStorage.setItem('shouldHide', true);
const reqresp = new XMLHttpRequest();
reqresp.onreadystatechange = function () {
if (reqresp.readyState == 4 && reqresp.status == 200) {
const counter = JSON.parse(reqresp.responseText).counter;
vm.$emit('got-counter', counter);
sessionStorage.setItem('counter', counter);

}
};
reqresp.open('GET', url, true);
reqresp.send();
}
}
}

Old browsers had to be supported (😢) and configuring Babel with build scripts was too much. While const works with IE11, fetch and arrow functions don’t.

Why having HTTP requests here? As you can see from the emitted event name, it is something connected with the new counter mechanism. We’ll come back to it later.

Also, to get around the multiple visits on refresh problem, we have sessionStorage. Why not localStorage? The answer is EU Cookie Law. It seems sessionStorage doesn’t require you to have this terrible Cookie Policy info on your webpage.

Files in clouds

How to host static files? AWS S3 (1) is the answer! S3 means SSS which means Simple Storage Service. Moreover, it can be configured to expose a bucket content as a website! I thought my job was done there.

It wasn’t.

source

OK, what is the “bucket”? It is something like a folder on your computer. Creating it is really simple, but there are some tricky parts.

  • Choose its name carefully. For the webpage like example.com, bucket should be named example.com as well. Moreover, the name has to be unique across all the existing AWS buckets
  • Always choose an appropriate AWS Region. A rule of thumb for simple scenarios: the same Region for all the services to minimize the costs (Internet transfer between different parts of the world). I decided to go with EU (Ireland)
  • Default options are OK in almost all the cases. However, your website should be available from the outside, so you should disable blocking public and cross-account access
AWS S3 Permissions

Then, you can create Bucket Policy to specify the mentioned open access:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example.com/*"
}
]
}

Having these things fixed, you can upload all the files to your bucket and go for Properties → Static website hosting. You need to choose a main file (index.html) and — optionally — an error file.

AWS S3 Properties

Domain?

If URL like http://example.com.s3-website-eu-west-1.amazonaws.com works for you, you can stop right now. But it wasn’t enough for me.

I had a nice domain, managed through OVH and I wanted to connect it with my S3 files.

Managing in OVH

First try was to add S3 URL as CNAME DNS record in OVH management tool. CNAME means Canonical Name and it can just lead to a different domain. Sounds good, doesn’t work — OVH requires providing an absolute URL. With “.” at the end. And using S3 address with a dot at the end leads to 404 error (NoSuchBucket).

At least, it happened to me.

AWS distribution

Googling a little never killed anybody. It appeared, there is a dedicated AWS service for distributing files, AWS CDN — CloudFront (2). Distributing files may not sound as the solution for the domain problem, but CloudFront offers some configuration options connected with this topic.

When creating a distribution, remember about a default root object:

CloudFront config

It took some time to distribute all the files, but then, loading the webpage with CDN URL was much faster.

Using this CDN URL as CNAME? Nope.

403 ERROR
The request could not be satisfied.
Bad request.
Generated by cloudfront (CloudFront)Request ID: xxx

CloudFront allows providing alternative domains, but you need a certification — a proof it is really your domain. I gave up and switched from OVH to AWS. It’s easier to configure the certification this way.

Managing in AWS

I started managing my domains from AWS Route 53 (3).

Warning: Route 53 is something you have to pay for. Each Hosted Zone costs like 0.62 $, including tax. Costs of S3, CloudFront and others are skippable for tiny scales. Moreover, as a new user, you have a free tier, but Route 53 has its fixed price.

The goal is to create a Hosted Zone in Route 53 for the domain and then, it is super easy to plug S3 or CloudFront URL there. Well… should be, but there are 2 things to be fixed first.

  1. DNS servers in OVH Control Panel
  2. HTTPS

Switching from OVH to Route 53 is as simple as playing with “DNS servers” tab in OVH Control Panel. Provide Route 53 servers there:

OVH DNS servers option

HTTPS

Why do we need it? Not even because it’s a standard nowadays, but because CloudFront requires it for its alternative domains.

CloudFront Distribution Settings

As stated in the above screenshot, you can use ACM (AWS Certificate Manager) (4) to get the SSL Certificate. It’s as simple as clicking

AWS Certificate Manager option

and going with default options.

I’ve just defined an Alternate Domain Name in CloudFront Distribution Settings and filled the SSL Certificate in. Then, I was able to add DNS A record in Route 53 and provide my CloudFront URL there.

Great success :D

Your safe & fast static webpage is ready! There are just 4 AWS services used for it :)

Bonus: CloudFront invalidation

What after changing something e.g. in index.html? Putting a new version in S3 is not enough, as CloudFront is cached for a long time.

In simple scenarios, you can go to your CloudFront distribution and choose “Invalidations” tab there:

CloudFront Invalidations

WarsawJS

We talk about JavaScript. Every month in Warsaw, Poland.

Mateusz (mat3e)

Written by

Programmer and IT Designer focused on #Frontend and integration technologies, with a relevant #FullStack experience. #JavaScript, #Java, #AI, #Technology.

WarsawJS

WarsawJS

We talk about JavaScript. Every month in Warsaw, Poland.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade