Configuring CloudFront to support push-state URLs
This one seems like an easy one, however I’m appalled by how much time can be wasted configuring AWS for static website hosting and there must be a better way:
— serverless: we will be hosting static assets so no messing around with servers for that
— cheap and ultra-performant: by leveraging AWS CDN, we’ll get world-class global distribution and caching for pennies
— automated: this is not a tutorial of the AWS console. Some of the marketing agencies I consult for would typically deploy new landing pages or static websites every week. If that’s something you do regularly too, it is worth investing an hour into automating this into a push-button procedure isn’t it?
There is something very powerful about automating even the little things. The benefits are much more than the sum of time savings over time, it will reduce human errors, improve the reliability of your service, get your employees busy with higher-value work and boost employee morale by eliminating boring low-value tasks. It improves your business globally.
A game changer: with Lambda@Edge, we can now configure CloudFront to support push-state URLs
The problem so far with hosting an SPA on CloudFront is that we couldn’t support push-state URLs because CloudFront doesn’t offer a “catch-all” configuration i.e. we couldn’t serve the same
index.html file for any request to the domain. The solution was to use hash-state “ugly” urls which was a turn-off for most.
In 2017, AWS released Lambda@Edge, a service that runs your Lambda functions “at the edge” of the cloud i.e immediately before/after the CDN queries its cache:
- viewer request: after CloudFront receives a request from a viewer
- origin request: before CloudFront forwards the request to the origin
- origin response: after CloudFront receives the response from the origin
- viewer response: before CloudFront forwards the response to the viewer
This will let us rewrite the requests on origin request so that we always serve
index.html for all push-state routes requests. Happy days!
What do I need?
- an existing domain name registered as a hosted zone in your AWS account
- a wildcard SSL certificate for all subdomains
awsCLI installed and configured on your machine
- a dummy React or Vue application to deploy
Show me the Terraform module!
I’ve released a Terraform module that does all the heavy lifting for you:
terraform-aws-single-page-application - Terraform module which lets you deploy SPAs on AWS using Git Pushgithub.com
Copy the example files into your SPA root folder:
Replace the values in
terraform.tfvars with your
aws CLI profile name, your app name and your domain name. Make sure you have an existing certificate for
*.cdn.mydomain.com in the us-east-1 region.
terraform init then
terraform apply and wait for the S3 bucket, Lambda function and CloudFront distribution to be created:
You can now compile your front-end assets locally and push them directly to the S3 bucket to deploy your application:
yarn build && aws s3 cp --recursive --acl=public-read build/ s3://$(terraform output s3_bucket)
An alternative is to use the CodeCommit Git repository and CodePipeline pipeline that has been created by the Terraform module to let AWS build your application, run your tests and deploy on S3.
Either way, your application is now running on CloudFront!