Next.js is a React framework that helps us to build isomorphic web applications easily. Isomorphic applications are those web applications which can be rendered either in the client side or in the server side. In a real world project, building an application and deploying it to server should be automized using any CI/CD tool. In this article, we will perform following steps.
Here, Gitlab is the Git server. It can be different for you like Bitbucket, Github and so on. Also, the CI/CD used is also from Gitlab. For other CI/CD tools, the syntax will be different but the base algorithm will be same.
First step in our process is to setup a Next.js application. For that you need to have Node.js installed in your machine. After that run following command in terminal.
Above command asks for a project name. It then creates a folder with that name and then setup your Next.js application in that folder. If you have difficulty in setting up a Next.js application, you can also refer to this article. Refer to Create Next.js Application section.
Next, create a repository in Gitlab and push the current code to the repo. My repository name is Next.js Intro.
The Gitlab repo looks like above.
Serverless is a NPM package using which we can upload our Next.js application to AWS Lambda. To install that, go to our Next.js app root folder and run below command.
npm install --save serverless
serverless package is added to our Next.js project. The package name is also appended to
dependencies section in
package.json file. Next, we need to create a new command in
package.json to invoke our serverless package. For that, open
package.json file of our Next.js application. Under
"scripts" section, add below key-value pair.
By adding above command, we can run
npm run deploy in terminal to invoke
serverless command runs, it executes the set of tasks written in
serverless.yml file. Right now, we do not have that file in our project. So, create a
serverless.yml in the project root folder.
In the yml file, add the following content:
myNextCICDApplication: component: "@sls-next/serverless-component@latest"
@sls-next/serverless-component is written exclusively for Next.js. By adding the reference to it in serverless.yml file,
serverless now know the steps to deploy our Next.js application to AWS Lambda@edge.
Ok, now serverless is ready to upload our Next.js application to AWS. But which AWS account? For that, we need to set two environment variables,
First take terminal. Navigate to the folder of our application. If you are using a Mac machine, run following commands to set environment variables.
export AWS_ACCESS_KEY_ID=<your access key id here> export AWS_SECRET_ACCESS_KEY=<your secret access key here>
You can confirm if the environment variable is properly set by running
printenv in Mac. For other OS, the command might be different.
After setting environment variables, run
npm run deploy in terminal. That will execute our
serverless command. We can see the deploying process.
Once the deployment is complete, the serverless component, gives the AWS cloudfront url to access our site.
Push the new changes to the project repo in Gitlab. The main changes are related to
serverless package. Just to ensure that we are in sync, our project structure now looks like this.
Now, its time to tell Gitlab CI/CD to handle the build and deployment. Gitlab has all necessary files to do that in the repository.
First we need to be clear about the expectation from Gitlab CI/CD. Here is the flow of process:
serverless is expecting a
serverless.yml file, Gitlab CI/CD expects a
.gitlab-ci.yml file in our project. A software called Gitlab Runner is the one who listens for change and execute the jobs defined in the yml file. We are going to implement the steps mentioned above in this
To start with, create
.gitlab-ci.yml file in the project root.
In order to run our project, we need a Node.js environment. We can use a Docker image here using
default: image: node:16.13.1
In Gitlab CI/CD yml file, we can define different jobs. A job contains a set of scripts to be executed. There are ways to run multiple jobs serially or parallely. Let us create a job in our yml file.
stages: - deploy aws-deploy-job: stage: deploy script: - npm install - npm run deploy
Before all jobs, we define stages. In our code, there is only one stage,
deploy. There can be multiple stages.
aws-deploy-job is a job name. That job is connected to
deploy stage. All the commands under
scripts are executed when this job is running.
When Gitlab runs our script, the serverless framework in our project will search for AWS credentials. It is there in our local machine, but not in Gitlab. We cannot directly and openly paste AWS credentials in
.gitlab-ci.yml file. That causes security breach. Instead, there is an option to define variables and their values in Gitlab console. This console can only be accessed by authorized users.
Let us set two variables in the console for AWS access key ID and AWS secret access key. For that, Go to Repo Settings > CI/CD > Variables section. Expand the section and add a new variable like below.
In similar manner, add another variable for Access Secret. Here is how the Variables sections looks finally.
We created two variables required for serverless Component. Since we did not change anything in the code, there is nothing to push to Gitlab. Instead, Go to Gitlab CI/CD pipeline and rerun the last failed pipeline. That will install all dependencies for the project using
npm install and after that, run serverless.
Now, when serverless is run by Gitlab CI/CD it has the needed AWS credentials from the environment variables. From now on, if we push any changes to our Gitlab repo, automatically the pipeline will run and deploy the updated site to AWS Lambda@edge.
We learned how to setup CI/CD pipeline for deploying our Next.js site to AWS Lambda. Now the pipeline is not production ready. Ideally, we setup different branches that maps to different environments(dev, qa, stage, prod). After that, when we push code to dev branch, deployment to dev environment happens, qa to qa environment and so on. We need to do update Gitlab yml file to manage our project like that.