“Serverless” SPA on AWS(Lambda, API Gateway, S3, CloudFront)
In this post we’ll dive deeper into the implementation of our Serverless SPA on AWS.
For background information and the setup of the React app, click here
Things to keep in mind:
- Authentication / Authorization are not a part of this simple architectural tutorial
- Neither is Security – our API is wide open and can be accessed by typing the API URL into the address bar
We’ll utilize 4 AWS services to complete our “serverless” demo:
- Lambda – for serverless computing
- API Gateway – to provide an http endpoint for our Lambda function
- S3(Simple Storage Service) – to store our static React application
- CloudFront – this is a global CDN(Content Delivery Network). We’ll use it to automatically distribute our static files to multiple regions to bring our code closer to our end clients around the world
High level tasks
- Create a Lambda function(source) and hook it up to AWS API Gateway
- Prepare React app for deployment by inserting the API Endpoint URL and building the app
- Upload the static files into an AWS S3 bucket
- Create a CloudFront CDN that will route all the requests to the index.html file
- Modify the Lambda function to accept CORS calls from our CloudFront domain, as well as the S3 bucket
Step by step instructions
- Login to console.aws.amazon.com – will be referred to as AWS Console
1. Create a Lambda function
- From AWS Console, click Lambda under Compute
- Click Get Started Now button
- On the Blueprint screen, select microservice-http-endpoint with nodejs(A specific blueprint is, more or less, irrelevant for our purposes – as long as it’s nodejs – since we’re going to replace the code with our own function. Having said that, the code in the gist was derived from this particular sample)
- On the Configure Triggers screen
- Type in an appropriate API Name for your project
- For Security choose Open
- On the Configure Function screen
- Give your function a Name
- Replace the current function code with this one
- Type in an appropriate Role Name(In this simple demo we don’t get to use it anywhere)
- Under Advanced Settings, limit your memory to 128mb
- Press the blue Next button
- Look over the configuration summary and click the Create function button
- Our Lambda function is now created – however not yet complete. We’ll come back to it when we have our S3 bucket URL and a CloudFront URL
- The API Gateway was created and integrated with our new Lambda function. Copy API endpoint URL for the next step.
2. Prepare React app for deployment
- Within the React app, open /src/App.js in your favorite editor and replace Line 23 with the URL of the API endpoint that was copied in the last step
- From the root(/) directory of the app, run command ‘yarn build’. This will bundle and minimize app code, and deposit the created static files into a created /build directory.
3. Upload static files to AWS S3(Simple Storage Service)
- Create the S3 bucket
- In AWS Console, find and click S3 under Storage
- Click the blue +Create bucket button
- Give bucket a Name, and click Next
- Click Next on the properties screen
- On the Permissions screen, under Manage public permissions, select Grant public read access to this bucket and click Next
- On the Review screen, click Create bucket
- The new bucket should now be visible within the bucket list
- In AWS Console, find and click S3 under Storage
- Click on the newly created bucket
- Drag and drop all files from the /build directory within your app into the blue area on the page
- Click Next
- On the Permissions screen, under Manage public permission, select Grant public read access to this objects(s)
- Click Next
- Click Next on the Properties screen
- Click Upload on the Review screen
- The files should now be uploading and will soon be visible in the bucket
- The following convention is used to access the files through a URL
- <bucket-name>-s3-<aws-region>.amazonaws.com/<file>
- In the case of the demo: m52-serverless-demo-s3-west-2.amazonaws.com/index.html
- <bucket-name>-s3-<aws-region>.amazonaws.com/<file>
- The app is now live, but CORS on Lambda prohibits us from interacting with the services. We will fix this once we set up our CloudFront CDN(which will also give us a friendlier, and a secure(!), URL)
4. Create a CloudFront CDN
- In AWS Console, under Networking & Content Delivery, find and click on CloudFront
- Click the blue Create Distribution button
- Under Web(the delivery method) click Get Started
- On the Create Distribution screen:
- Under Origin Settings, find and select the newly created bucket in the Origin Domain Name
- Under Default Cache Behavior Settings, change the Viewer Protocol Policy to Redirect HTTP to HTTPS
- Under Distribution Setting, for the Default Root Object enter index.html
- Click the blue Create Distribution button
- Take note of the Domain Name – just as the S3 bucket domain name, we will need to update CORS settings on the Lambda function to accepts these two origins
The CDN will take a few hours to propagate to the edge locations around the world and will serve files from a location closest to the client, thereby decreasing latency and increasing overall app performance. In the mean time, we’ll complete our final step – place the S3 bucket and CloudFront URLs into accepted origins in the Lambda function for CORS communication.
5. Modify Lambda CORS origins
- In the AWS Console, under Compute, find and click on Lambda
- Choose the Lambda function that you created in Step 1
- Under the Code tab, replace lines 14 & 15 with your CloudFront & S3 URLs
- Click the Save button
Once the files have propagated you should be able to go to the CloudFront domain that’s assigned to your CDN, refresh the browser and see the following:
Congrats on your first “serverless” deployment on AWS!
Comments and discussion are very welcome!
PS. Don’t forget to delete the resources not to incur perpetual cost.