I am currently designing a simple Serverless Web App using Serverless.
My current expected stack is;
I have followed a few tutorials for building the Serverless API, Lambda and DynamoDB using the Serverless Framework and I have built my single page app however right now they are 2 separate entities.
What I am looking to do now is bring the static site (nodejs) into the same project as my API, Lambda and DynamoDB and use the Serverless Framework to control the deployment however I'm struggling to find guidance on;
Could anyone provide any insight into how this is supposed to work, or maybe point me int he direction of some good blogs/resources?
Kind Regards, John
I had a SPA (single page application) written in React communicating to a REST JSON API written in nodejs and hosted on Heroku as a monolith. I migrated to AWS Lambda and split the monolith into 3+ AWS Lambdas micro services inside of a monorepo The following project structure is good if your SPA requires users to login to be able to do anything. I used a single git repository where I have a folder for each service:
Inside of each of the services' folders I have a serverless.yml defining the deployment to a separate AWS Lambda.
Each service maps to only 1 function index
which accepts all HTTP endpoints. I do use 2 environments staging
and production
.
My AWS Lambdas are named like this:
I use AWS Api Gateway's Custom Domain Names to map each lambda to a public domain:
www.example.com (server side rendered landing pages)
api-staging.example.com
You can define the domain mapping using serverless.yml Resources or a plugin but you have to do this only once so I did manually from the AWS website console. My .com domain was hosted on GoDaddy but I migrated it to AWS Route 53 since HTTPS certificates are free.
app service
The app service contains a folder /src with the single page application code. The SPA is built locally on my computer in either ./bundles-production or ./bundles-staging based on the environment. The built generates the .js and .css bundles and also the index.html. The content of the folder is deployed to a S3 bucket using the serverless-s3-deploy plugin when I run serverless deploy -v -s production
.
I defined only 1 function getting called for all endpoints in the serverless.yml (I use JSON instead of YAML):
...
"functions": {
"index": {
"handler": "handler.index",
"events": [
{ "http": "GET /" },
{ "http": "GET /{proxy+}"}
]
},
},
The handler.js file returns the index.html
defined in /bundles-staging or /bundles-production
I use webpack to build the SPA since it integrates very well with serverless with the serverless-webpack plugin.
api service
I used aws-serverless-express to define all the REST JSON API endpoints. aws-serverless-express is like normal express but you can't do some things like express.static()
and fs.sendFile()
.
I tried initially to use a separate AWS Lambda function instead of aws-serverless-express for each endpoint but I quickly hit the CloudFormation mappings limit.
www service If most of the functionality of your single page application require a login it's better to place the SPA on a separate domain and use the www domain for server-side rendered landing pages optimized for SEO.
BONUS:
graphql service Using a micro service architecture makes it easy to experiment. I'm currently rewriting the REST JSON API in graphql using apollo-server-lambda
I have done pretty much the same architecture and hosted the single page app on s3. What you can do is set up cloudfront for api gateway and than point api.yourDomain.com to that cloudfront. Than you will also need to enable cors on your api.
This plugin handles setting up domain and cloudfront for you:
https://github.com/amplify-education/serverless-domain-manager
I am not sure about your project requirements but if you want to serve static files faster setting up domain->cloudfront->s3 might be a wise choice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With