Deployment of NextJs app in S3 using AWS CI/CD tools
Published: 2023-03-20 08:30:34

Hey there, in this article, I am going to walk you through the process of deploying a Next.js app using AWS CI/CD tools, `CodeCommit `and `CodePipeline`. Before we begin, make sure you have an AWS account and are familiar with the basic concepts of AWS and Git flow.

## Step 1: Create a Next.js app

First, let's create a new Next.js app using the command line. You can choose to create it with TypeScript by using the flag --typescript.

```
yarn create next-app my-next-app
cd my-next-app
```

---

## Step 2: Create a `CodeCommit `repository

Now that we have our app set up, let's create a new repository in AWS `CodeCommit `to store our code. To do this, go to the AWS `CodeCommit `console and click on the "Create repository" button. 
For this you can follow given steps shown in images. 

Click on `Create repository` button you will see the following console. Here you need to write a name of your repo and add description if you want (It is optional). After that, hit `Create button`. 

![step 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m2dy9nfidy1zzhiscneh.PNG)

After creating repo, you will see the following instructions in the console. Please go through the each steps_(personal recommendation)_. Under the step 3 section, you will find the git command to clone this repo.

![step 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnjzc9vxxzyoz4wszub9.PNG)

Now for cloning this repo, you must be able to create the Git credentials. You can follow this [steps](https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-gc.html?icmpid=docs_acc_console_connect_np) shown in official documentation.

Add this git origin to your existing code base. If you are not familiar with this steps go through [this](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) official documentation.

---


## Step 3:Create a `CodePipeline `for deployment

Next, we need to create a new `CodePipeline `in AWS `CodePipeline `to handle the deployment of our app. Go through this steps.  

In the AWS `CodePipeline `console, click on "Create pipeline" and follow the steps as shown in the images below and hit Next. Here you can select the `New service role` and AWS will create a new role for you. You need to edit this role later which is described in the step 5 below. 

![step 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfk3sa7w3yzbzrli8h7v.png)

In the Next step add the source provider. The source provider( code container) for our app is AWS `CodeCommit `so choose the one. Here, choose the repository name and the branch name(main branch usually "master" or could be any like "develop", "main" etc) respectively and leave all other configuration as default and hit Next.

![step 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npnriza0rj6ipd9p6tob.PNG)

Once you are done with the second step, third one is pretty important one. Here you will going to choose the build provider. You can choose any one but here I am sticking with the `AWS CodeBuild`. Once you select this option, you will see other configuration options where you need to leave as default and only need to create a project name.

![step 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghu3pnk9a10wpvpzld5k.png)

while creating the project, leave everything default. And In the environment section, for **Operating System**, choose `Amazon Linux 2 ` and choose `standard` Runtime. 

![step 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7u4vy8zpu1vyulgnlq1d.png)
In the **Buildspec** section you can give any custom name for the build yml file. For now choose `buildspec.yml` which is the default one and leave all other configuration as it is and hit **Continue to CodePipeline**.

![step 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gz4w39h9b3kp09kd4lp.PNG)

Now, you will be redirect to previous step and console will show your project. Now hit Next button.

In this step you have to specify the deploy provider. Choose S3 for now and mention Bucket name and check the `Extract file before deploy` checkbox as shown and hit Next. 


![step 6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13cwvfxghgkzd2lscbfk.PNG)

Now review all the settings and create the pipeline. You may see automatic progress of the deployment where your build process will fail. So, don't get panic, we still have two more configuration to complete.

---

## Step 4: create the IAM policy
As our pipeline needs access to the **S3 **and **CloudFront **services. So, Go to the deployment section to see all the logs by clicking the following link as shown in image.

![step 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8j19ba7sn9wxw72i6493.png)

Now under the **Build details** tab you will see Service role (created at Step 3 while naming the pipeline). Click in the role and you will be redirect to the IAM console.


![step 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6z2ir3xh0wdvc6ql0x1.png)

Now Attach the inline policies as shown in the figure below for **S3** write (PutObject) and **CloudFront** write (CreateInvalidation)


![step 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oaq53lb9h06phn6jngqh.png)

After going to the Create Policy console follow this steps.

1. First choose the service **s3**.
2. Under Actions section, expand write box and choose `PutObject`.
3. Mention S3 bucket and object.
4. Again click on `Add additional permissions` section and choose service **CloudFront**
5. Under Actions, expand write box and choose `CreateInvalidation`.
6. create the policy. 

---

## Step 5: create a `buildspec.yml` file in the vs code

Now you need to create `buildspec.yml` file in the root directory_(where your project's node_modules directory lies)_ in vs code. create the file and paste the given map. 

```
version: 0.1

phases:
  pre_build:
    commands:
      - yarn install

  build:
    commands:
      - yarn run build

  post_build:
    commands:
      - aws s3 cp --recursive public-read ./build s3://<bucketname>/
      - aws s3 cp public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/index.html s3://<bucketname>/
      - aws cloudfront create-invalidation --distribution-id <your-cloudfront-id> --paths /index.html

artifacts:
  files:
    - 'build/*'
    - 'build/**/*'
```
The YAML file described above is quite simple. 

- In the `pre_build` stage, the script installs all necessary NPM package dependencies.

- During the build stage, the script runs the `yarn build` command to compile and bundle the web app into the build directory. 

- In the `post_build` phase, the script carries out three operations. Firstly, it copies all contents of the build directory to the designated **S3 **bucket and makes them publicly accessible. Next, it copies the `index.html` file once more and sets particular caching HTTP headers to prevent the file from being cached by browsers. Finally, it creates an "_invalidation_" that instructs the **CloudFront **distribution to refresh its content from the S3 source bucket.

---
 
## Step 6: Push the code to the origin 
At this point, we have now finished all the configuration that needs to be done in AWS for `CodeBuild` to deploy our `NextJs `app to **S3**. So, commit the changes and push the branch to the repository. You will see `progress` tag when clicking will shows you a deployment progress and after some minutes your code will be deployed to S3. The complete process looks likes this.


![complete deployment process](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swykd69363ulgpkfeaa6.PNG)

Hope you enjoyed the article and learned a new skills today. If you want more from me then don't forget to follow. Also, If you have any queries or feedback then please comment. Thank you and happy deployment!