Deployment

Deployement on AWS

Serverless Architecture

Next.js has included Serverless Mode since v8, meaning using servereless with Next.js v12 is quite standard.
with Serverless Mode in Next.js, developers can continue to use the developer-friendly, integrated environment of Next.js for building applications, while also taking advantage of Serverless Architecture by breaking up the app into smaller pieces at deployment to Serverless Architecture.

We have 3 main componenets :

  • AWS S3 : Will be used to store cach + static files
  • AWS CloudFront : Used for distribution
  • AWS Lambda : will be used to deliever dynamic content + server-side rendred pages.

IaC : Infrastructure as Code

Infrastructure as Code (IaC) is the managing and provisioning of infrastructure through code instead of through manual processes.With IaC, configuration files are created that contain your infrastructure specifications, which makes it easier to edit and distribute configurations. It also ensures that you provision the same environment every time.
By codifying and documenting your configuration specifications, IaC aids configuration management and helps you to avoid undocumented, ad-hoc configuration changes.
In additin, Automating infrastructure provisioning with IaC means that developers don’t need to manually provision and manage servers, operating systems, storage, and other infrastructure components each time they develop or deploy an application.

IaC in the context of Serverless

When we decide to implement IaC to deploy our serverless Next.js app, following are the options available :

  1. CloudFormation
    AWS CloudFormation is a service within AWS that lets you group resources (usually AWS resources) into stacks that you can deploy and continuously update. These CloudFormation templates are written in JSON or YAML and manually typing those can be very tedious.

  2. AWS Serverless Application Model (SAM): Yet a brief Transform of CF
    From CloudFormation's perspective, SAM is a transform. Meaning: SAM templates are syntactically equivalent, but they allow you to define your serverless app with more brevity. The SAM template eventually gets expanded into full CFN behind the scenes . If you already know CFN, but want to write less YAML code, SAM may be beneficial to you. The idea is to reduce your effort.

  3. AWS Cloud development kit (CDK): Use Typescript to write IaC
    The AWS CDK went into general availability in the summer of 2019 and has been getting a lot of traction lately. It is an open source framework that lets you create your infrastructure as code instead of CloudFormation. You then generate CloudFormation templates from your code by running the command CDK SYNTHESIZE. You can choose from Python, TypeScript, JavaScript, .NET and Java to describe your resources instead of having to do it in pure CloudFormation.

  4. Serverless Framework : Mature solution in context of Next.js
    This one has been around since 2015 and was called JAWS before quickly changing to its current name. As the very descriptive name says, it’s a framework for building serverless applications! The framework is easy to get started with and setting up an API with a few Lambdas require very little configuration for the developer as the framework takes care of the underlying CloudFormation template. Serverless Framework is open source and multi-cloud. It’s also extendable with a wide range of plugins created by the community.

  5. Terraform Cross cloud solution
    This multi-cloud tool for infrastructure as code is worth a mention! It has been around since 2014 and is written in Go. For AWS it uses the aws-sdk to manage resources instead of CloudFormation,

IaC Solution used : Serverless Framework

Serverless Framework is the major, ready-to-go solution now to deploy Next.js app as a serverless application, Since on the official Next.js docs section, more specificaly when documentating possible deployement options, in case of serverless deployement, it is recommended to opt for the servereless-nextjs component by the servereless framework.
ref: Next.js deployment (opens in a new tab)

Serverless Next.js Component

The Serverless Framework is a tool to make deploying to cloud platforms a lot easier, automating provision by allowing you to define your projects infrastructure as yml.

We are using Serverless Framework Nextjs componenet : github repo (opens in a new tab)

The Serverless Next.js Component is built with three design principles in mind.

  • Zero configuration by default
  • Feature parity with Next.js
  • Fast deployments

Feature parity with Next.js

This design principle states that the features available in Next.js should be available with the serverless component. For a list of features available, you can check the docs (opens in a new tab).

version : 3.7.0
We need a file serverless.yml where we define the configuration for the deployement.

example:

name: prod-phpr
 
prod-phpr:
    component: '@sls-next/serverless-component@3.7.0'
    inputs:
    bucketName: prod-phpr-s3
    description: 'Lambda@Edge for prod-phpr'
    name:
    defaultLambda: prod-phpr-lambda
    apiLambda: prod-phpr-lambda # domain: ['staging', 'phprui.com']
    publicDirectoryCache: false
    removeOldLambdaVersions: true
    runtime:
    defaultLambda: 'nodejs16.x'
    apiLambda: 'nodejs16.x'
    cloudfront:
    distributionId: E20GRZUAQC9KWI
 

After Configuration, we run the command $ serverless [ Make sure to install serverless CLI, refer to official serverless website (opens in a new tab), one caveat is that v3 of the cli is not working, thus we used v2 , take a look also at the open issue on the github repo : issue with cli v3 (opens in a new tab), issue is with the cli, not the componenet itself ]

After the deploy is completed, we will have 3 ressources created on AWS :
  • S3 bucket
  • cloudFront distribution
  • Lambda function

How does cache work in CloudFront?

Four Cache Behaviours are created in CloudFront.

The first two _next/* and static/* forward the requests to S3.

The third is associated to a lambda function which is responsible for handling three types of requests.

  1. Server side rendered page. Any page that defines getInitialProps or getServerSideProps method will be rendered at this level and the response is returned immediately to the user.

  2. Statically optimised page. Requests to pages that were pre-compiled by next to HTML are forwarded to S3.

  3. Public resources. Requests to root level resources like /robots.txt, /favicon.ico, /manifest.json`, etc. These are forwarded to S3.

The reason why 2. and 3. have to go through Lambda@Edge first is because the routes don't conform to a pattern like _next/* or static/*. Also, one cache behaviour per route is a bad idea because CloudFront only allows 25 per distribution.

The fourth cache behaviour handles next API requests api/*.

Improtant! Certificate for 2 level subdomains [staging.ticket.phpr.link]

subdomains like dev.phpr.link are automatching with the correct SSL ceritificate, while 2 level subdomains need to have SSL certificate for each subdomain :

Head to AWS certificate manageer (opens in a new tab) and request certificate for the subdomain ticket.phpr.link, once requested, you will need to verify dns ownership, For this, choose the newly created certificate ( still in pending), and click on Create records in Route 53 then follow it , it will automatically create dns records on the 53 route.

Finally, Add the Certificate Arn to the serverless file

...
 
   domain: ['staging.config', 'phpr.link']
    certificateArn: 'arn:aws:acm:us-east-1:566893917376:certificate/412a2338-3aab-40fb-9a64-0ea38107f488'
...

Interesting Articles