I was building a single page application and did not want to publish it externally, but wanted to put it on a non-local server to test delivery, so here are my notes on building it.
Elements
Since it was a static distribution and S3 seemed to be able to do it with only AWS services without setting up a server, we assumed the following.
- Serverless (use existing services, do not launch instances)
- Static delivery over https
- http communication is not allowed
- Not cached (so that you can see updates as soon as they are uploaded)
- Routable by subdirectory
- Access Restriction by IP Address
procedure
HTTPS static delivery
I was thinking that I could just put the files in S3 and use Static website hosting, but I needed to use CloudFront for https delivery. Also, if I used CloudFront to deliver the files, there was no need to publish S3 with Static website hosting.
From the Distributions page of CloudFront, go to [Create Distribution]-[Web]-[Get Started] to create a distribution.
Origin Settings
- Select the bucket to publish
Origin Path
- Specify which subdirectories to publish. The first letter "/" and the last "/" are not necessary.
Restrict Bucket Access
- If you publish using CloudFront, you do not need to publish S3. Set to "Yes".
Origin Access Identity
- Identity is required, but if you have not created one, use "Create a New Identity" to create one.
Grant Read Permissions on Bucket
- Good. It will set the permissions and I will set it to "Yes".
Default Cache Behavior Settings
- We want only HTTPS delivery, so we set "Redirect HTTP to HTTPS".
Object Caching
- Since this is a development site, we want to check the files as soon as they are uploaded, so we select "Customize" to set the site to not cache files.
Minimum TTL・Maimum TTL・Default TTL
- Cache time setting. Set to "0" as we do not cache
Distribution Settings
- IP restrictions can be applied here. You can set it to "None" as it can be set later.
Default Root Object
- Specify the file name of the HTML to be delivered for the single-page application.
Press the "Create Disctibution" button to create the distribution. It takes quite a while. Perhaps it will take longer than you imagine, and you may worry during the process whether it is working, but it will be completed when you forget about it.
Routing by subdirectory
In a single-page application, you may have to use subdirectories for routing.
With the default settings, there is no file in the subdirectory, so an error is generated. Therefore, we will set it up so that it calls the delivery page instead of the error.
Open the distribution details you just created and press the [Error Pages]-[Create Custom Error Response] button to add behavior for each error.
- Select "404."
Customize Error Response
- Select "Yes" to display the delivery page instead of the error page.
Response Page Path
- Specify the name of the application delivery HTML file.
HTTP Response Code
- Select "200."
Create error code "403" in the same way.
This will cause the delivery page to be called instead of an error when the subdirectory is accessed.
Browser Cache Time Settings
The cache time set in CloudFront is the CloudFront cache time, not the browser cache time. Even if the CloudFront cache time is set to 0, if caching is enabled in the browser, accesses will not be updated. Therefore, you need to disable the browser cache separately.
How much the browser caches the file is determined by the "Cache-Control" in the header when the file is retrieved, and if the value is "no-chache, no-store" the browser will not cache the file.
To set "Cache-Control" in CloudFront, set it in the "metadata" of the big file placed in S3.
aws s3 cp --recursive --metadata-directive "REPLACE" \ --cache-control "no-cache, no-store" \ $LOCAL_PATH "s3://${UP_PATH}/"
Access Restriction by IP Address
Create an access restriction setting (=ACL) in AWS WAF and assign it to CloudFront distribution.
In the Delivery Details, specify the ACL you created in [General]-[Edit]-[AWS WAF Web ACL].
- Create IP addresses to be allowed in [IP addresses].
- Create a rule "When a request [does] [originate from an IP address in] [the IP address created above]" when matching a specified IP address in [Rules].
- Add the above rule in [ACL] and set "Action" to "Allow" and "Default action" to "Block
Now, when the URL created by CloudFront is accessed, the SPA starting from "index.html" uploaded to S3 will be loaded.