Single Page Apps or SPAs are quite popular nowadays and developing a nice frontend using frontend frameworks like Angular or React is a breeze. However, when it comes to deploying these apps to a production environment (the cloud), things can quickly become complicated, as topics like high availability, cost optimisation, performance (low latency), caching, come into play.
For a frontend developer with limited cloud expertise, this can be a problem. Luckily, AWS CDK makes things so much easier from an operational perspective. However, knowing how to build the right blocks is still a requirement. Let me try to help.
In this example, we’ll create a regular S3 bucket that will store the static files of our frontend (think of the /dist folder of Angular, where the compiled output of the frontend app is emitted as artifacts). That bucket will be “private”, meaning that it will be inaccessible directly from the internet.
Instead, we’ll use CloudFront as the entrypoint to the files within the bucket. By using CloudFront, we take advantage of its high availability, global distribution of edge locations (that’s because it’s a CDN service) and caching settings.
Let’s start by creating a simple website inside the /dist folder:
From the infrastructure (AWS CDK) side, let’s create the S3 bucket that will hold the website:
Note: Do not use the websiteIndexDocument or websiteErrorDocument props of the Bucket construct if you follow this example closely. Passing these will cause the Bucket to be automatically configured as “website enabled”, which makes the CloudFront examples below stop working.
How do we upload the /dist folder (our website’s file) to the S3 bucket? We could do it through the AWS CLI, the AWS Console or another manual mechanism, but personally I prefer to automate stuff as much as possible. CDK already provides a built-in mechanism to auto-upload a directory to an S3 bucket. It’s called the BucketDeployment construct. Here’s an example of how to use it:
Make sure to adjust the path to your dist folder if needed.
Now, when you try to browse the URL of the bucket, e.g.
https://awscdks3staticwebsitestack-bucket83908e77-h0p2uea4pavv.s3-eu-west-1.amazonaws.com/, you should be faced by an AccessDenied error, which indicates that we have correctly configured our S3 bucket from a privacy perspective. People can not access it directly by randomly guessing its URL.
Let’s now create a “public” entrypoint to our bucket – the CloudFront distribution:
Remember to pass the OriginAccessIdentity to the S3Origin, as well as grant it permissions to the S3 bucket, because this makes the CloudFront service be able to securely read and serve files from the private S3 bucket.
Now, when we deploy everything, get the Cloudfront URL (e.g. https://d1c91p94te958.cloudfront.net) and try to access it in the browser, we should be able to see our website.