DEV Community

Cover image for Deploying a React Application to AWS Cloudfront
Kelechi Oliver A.
Kelechi Oliver A.

Posted on

Deploying a React Application to AWS Cloudfront

Ever wondered how to deploy your single page React application to AWS Cloudfront service?. In this article I would be showing you how to deploy a sample React application to AWS Cloudfront

We would be deploying

  • Manually using AWS cloud console
  • Automated using Github Action
Components

AWS Cloudfront: This is a content delivery network (CDN) provided by Amazon. Users access content through AWS nearest edge location. It can be used for delivering fast and secure websites, accelerate dynamic content delivery and api’s, stream live and on demand video.

AWS S3: This is a cost effective, highly performant object storage service provided by Amazon. It allows you to store objects such as documents, video, images, blobs, etc. It can be used for backups, cold storage, file storage, archiving, web frontend host, etc.

Github Action: Github Action is an automation tool for automating developers workflows, just like CircleCI, Jenkins, it can be used to create CI/CD pipelines.

Deployment
As shown on the diagram below, we would be uploading our static assets (html,js,css) to S3 and then creating a Cloudfront distribution to use the uploaded asset. On subsequent deployments we would invalidate the existing distribution to enable Cloudfront fetch new content from S3.

Image description

Manual Deployment
In order to manually deploy to Cloudfront ensure you have the following

  • An AWS account with access to create S3 buckets and Objects as well as create Cloudfront distribution. Your normal AWS account would do, if you’re an IAM user ensure you have those permissions
  • A sample React application, you can clone one here

First, let's get our static assets ready. Depending on your package manager (npm or yarn) run npm install to install dependencies and npm run build to build project, doing this would populate our build folder with the built assets (html,css,js etc)

Next, Open your browser and login to your AWS account, search and select S3 from services, create a new bucket with the following fields

Bucket name: Enter a globally unique name
Leave the other fields default, and click “create bucket”.

Click to Select the newly created bucket, click upload and upload all files in the build folder.
Image description

Next, create a Cloudfront distribution, search and select Cloudfront from services, click “create distribution”, on the creation form, do the following

Origin domain: select your new s3 bucket name
S3 bucket access: select “Yes use OAI (bucket can restrict access to only CloudFront)”
Origin access identity: click “Create new OAI”
Bucket policy: select “Yes, update the bucket policy”
Click “Create distribution”
Image description

This would create a new distribution and update your S3 bucket policy, allowing Cloudfront to get objects.

Next, lets update the distribution error pages, Click on your newly created distribution and at the top tab menu click “Error pages”, then click “Create custom error response”, fill in the following

HTTP error code: select “443: Forbidden”
Error caching minimum TTL: enter 30
Customize error response: select “Yes”
Response page path: enter “/index.html” without the quotes
HTTP Response code: select “200:OK”

Finally, click “Create custom error response”.
Repeat these steps with HTTP error code “404”
Image description

Finally, let's check our application. With the distribution selected, click on the “General” tab, under details, click on the square like icon to copy the distribution domain name, paste this on a new browser tab to test application deployment.
Image description

Note: ensure you’re not seeing a “Deploying” status under Last Modified, if so wait till it’s complete.

After all these is done, when next you update your application code, and needs to redeploy, just build and re-upload your new assets to the same bucket created earlier, this would overwrite the existing files, then move over to your cloudfront distribution, selected distribution and click on the “Invalidations” tab, click “Create invalidation”, under “Add object paths” enter /*, finally click “Create invalidation”. This would invalidate the cached assets on Cloudfront while updating the distribution with the newly uploaded assets on S3.
Image description

Automating Deployment with Github Action
Here we would be automating the manual steps above using Github Action, to follow along ensure you have the following

  • AWS CLI user, this can be done by going to IAM service on AWS console, and creating a new user with programmatic access and Administrative permission, copy the account secret id and secret key, we would be needing it
  • Github repository with sample react application

With our S3 bucket and Cloudfront distribution created, we would be using Github Action to automate building and deployment of our frontend application whenever a push is made to the repository’s master branch.

First, on S3 we’ll need to enable Access Control List (ACL) to allow our CLI user with programmatic access to push objects to an S3 bucket created by another user. Open your bucket, click on the permissions tab, scroll down to Object Ownership, click edit, select “ACLs enabled”, select “Object writer” and click “Save changes”, scroll down to “Access control list (ACL)” while on permissions tab check that your CLI user canonical id is on the ACL, if it isn’t add it by clicking edit, click add “grantee”, paste in your CLI user canonical id and select “list”, “write” access then click “Save changes”.
Note: you can run the following command on your terminal to check your CLI user canonical id aws s3api list-buckets --query Owner.ID --output text, ensure you have AWS CLI with credentials setup on your terminal before doing this
Image description

Next, push your sample application code to Github, login to Github and select the repository, click on the settings tab

Let’s add secrets that’ll be used in Github action, on the sidebar menu, click “Secrets”, then click “Actions”, click “New repository secret” to add a repository secret that would be used by Github Action.
Image description

Next, enter the name of the key AWS_ACCESS_KEY_ID, and for value, paste in the value of your programmatic AWS user access key id, click “Add secret”. Repeat this step for AWS_SECRET_ACCESS_KEY and “AWS_DEFAULT_REGION”, for AWS_DEFAULT_REGION you can type in any region of choice such as us-east-1.
Here you can also add any environment variable used by your application
Image description

Next, create an action workflow file for our project, still on the repository, click “Actions”, click “set up a workflow yourself” and paste in the script below.

name: Frontend Cloudfront Deployment

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]
    steps:
    - uses: actions/checkout@v2

    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}

    - name: Yarn Install
      run: yarn install

    - name: Yarn Build
      run: yarn build
      env:
        REACT_APP_API_URL: ${{ secrets.REACT_APP_API_URL }}

    - name: Share artifact inside workflow
      uses: actions/upload-artifact@v1
      with:
        name: build-artifact
        path: build

  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      # get build artifact
      - name: Get artifact
        uses: actions/download-artifact@v1
        with:
          name: build-artifact

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

      # Copy build to s3
      - name: Deploy to S3
        run: |
          S3_BUCKET=s3://<s3-bucket-name>
          aws s3 sync . $S3_BUCKET --acl private
        working-directory: build-artifact

      - name: Create Cloudfront Invalidation
        run: |
          DISTRIBUTION_ID=<distribution-id>
          aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths /*
        working-directory: build-artifact
Enter fullscreen mode Exit fullscreen mode

Replace <s3-bucket-name> and <distribution-id> with your bucket name and distribution id respectively. From the script you can find references to our secrets created earlier.
Click “Start commit”, add a commit message and commit directly to master.
Image description

Finally, click on “Actions” to see your newly created workflow running, once this is completed, open your Cloudfront url to see the updated application.

I’m glad we made it this far 👏, we’ve covered a lot. For a more detailed explanation please check the video here. I made a video to properly explain the steps, so if you’re having issues just watch the video.

Perhaps you find this helpful, please leave a LIKE, Cheers!

Top comments (0)