Serverless Nextjs Component
A zero configuration Nextjs 9.0 serverless component with full feature parity.
Contents
Motivation
Since Nextjs 8.0, serverless mode was introduced which provides a new low level API which projects like this can use to deploy onto different cloud providers. This project is a better version of the serverless plugin which focuses on addressing core issues like next 9 support, better development experience, the 200 CloudFormation resource limit and performance.
Design principles
- Zero configuration by default
There is no configuration needed. You can extend defaults based on your application needs.
- Feature parity with nextjs
Users of this component should be able to use nextjs development tooling, aka next dev
. It is the component's job to deploy your application ensuring parity with all of next's features we know and love.
- Fast deployments / no CloudFormation resource limits.
With a simplified architecture and no use of CloudFormation, there are no limits to how many pages you can have in your application, plus deployment times are very fast! with the exception of CloudFront propagation times of course.
Features
Getting started
Install the next.js component:
npm install serverless-next.js --save-dev
Add your next application to the serverless.yml:
myNextApplication:
component: serverless-next.js
Set your aws credentials in a .env
file:
AWS_ACCESS_KEY_ID=accesskey
AWS_SECRET_ACCESS_KEY=sshhh
And simply deploy:
$ serverless
Custom domain name
In most cases you wouldn't want to use CloudFront's distribution domain to access your application. Instead, you can specify a custom domain name.
First, make sure you've purchased your domain within Route53. Then simply configure your subdomain
and domain
like the example below.
myNextApplication:
component: serverless-next.js
inputs:
domain: ["www", "example.com"]
Architecture
The application architecture deployed by the component is the following with minor variations:
FAQ
Is it one monolith Lambda or one Lambda per serverless page?
One master lambda is provisioned, then CloudFront behind the scenes creates replicas at the edge locations.
There are a few reasons why all pages are deployed onto one lambda:
-
Simplicity. One lambda responsible for server side rendering or serving the API requests is very easy to manage. On the other hand, one lambda per page is a large surface area for a web app. For example a next application with 40+ pages would have resulted in 40+ lambda functions to maintain.
-
Deployment speed. Is much faster building and deploying one lambda function.
Of course there are tradeoffs ... An architecture using one lambda per page in theory results in lower boot times. However, the implementation of this component is designed to ensure a minimum amount of compute happens at the Lambda@Edge.
How do I interact with other AWS Services within my app?
See examples/dynamodb-crud
for an example Todo application that interacts with DynamoDB.
Users are encouraged to use this component instead of the serverless-nextjs-plugin
. This component was built and designed using lessons learned from the serverless plugin.