Deploying a React App to Amazon S3 with Bitbucket Pipelines.

Eric Wein
5 min readOct 8, 2019

--

This walk through is a simple step by step guide to deploying a React Web application to Amazon S3 using Bitbucket Pipelines.

I recently had the task of setting up a CI/CD pipeline for a React application. I looked at using a few different services but because our code is residing in Bitbucket I ultimately settled on Bitbucket Pipelines. This being the first time setting up a pipeline using Bitbucket Pipelines I thought I would create a guide for anyone else looking to do the same. This walk through will be broken into 3 sections and assumes you have a basic knowledge of AWS services such as S3, Cloudfront and Route 53.

  1. Creating an S3 bucket
  2. Creating a Cloudfront Distribution
  3. Enable and Configure Bitbucket Pipelines

Lets get started!

Step 1: Creating an S3 Bucket

The first step in the process is creating an S3 Bucket where the static React application data will be stored. If you want to learn more about what an S3 bucket is you can do so here.

  1. Start by navigating to the S3 dashboard and selecting “Create Bucket”. Create a unique name for your S3 public and hit Next.
  2. Skip ahead to the “Block Public Access” screen and deselect “Block all public access” so the React app is publicly available.
  3. Back in the bucket list, select the newly created bucket and navigate to the properties tab.
  4. Next, select “Static Website Hosting” and “Use this bucket to host a website”.
  5. Set the index and error documents to both index.html. This will allow the React application to handle the routing.
  6. After that is configured, the bucket is ready to go.

Step 2: Create Cloudfront Distribution

Amazon Cloudfront is a content delivery network (CDN) that allows our application to be delivered globally with low latency and high transfer speeds. Cloudfront uses a series of edge locations to host our application globally so where ever you are you will get the content from the closest node increasing delivery speed.

  1. Start by navigating to the Cloudfront dashboard and selecting “Create Distribution”.
  2. Select Web for the distribution and set the origin name — should be the bucket you just created.
  3. Select to redirect HTTP to HTTPS and select which edge locations you want to support.
  4. If you have a domain you want to connect to the Cloudfront distribution you must provide an alternate domain name. The alternate domain name should match the domain you plan to connect to the distribution in Route53.
  5. Provide an SSL certificate that matches the alternate domain.
  6. Leave everything else the same and create the distribution.
  7. Back in the distributions list, select the newly created distribution and go to Distribution Settings.
  8. Navigate to the Error pages tab and select to create a custom error response. Again we want to pass the error handling to our React app. We will force the errors to be handled by index.html.
  9. Set:
  • HTTP Error Code = 403
  • Caching TTL = 0
  • Custom Error Response = true
  • Response Path = /index.html
  • Response Code = 200

10. When you deploy your React application you may notice that your changes are not reflected. This is due to Cloudfront caching, to clear the cache we will need to create a Cloudfront invalidation. You can do this manually by navigating to the Invalidations tab and selecting Create Invalidation. Set the Object Paths to * to invalidate the entire cache. However, we can automate this process by adding a pipe to the bitbucket-pipelines.yml file (see below).

11. Cloudfront is now connected to your S3 bucket and is ready to go.

Step 3: Enable and Configure Bitbucket Pipelines

Pipelines is the integrated deployments service provided by Bitbucket. It makes setting up a CI/CD pipeline trivial with the use of Bitbucket pipes. Pipes are pre-configured blocks that allow you to interact with various services such as AWS and Slack. Read more about pipes here.

  1. Navigate to your Bitbucket repository and select Settings → Pipelines → Settings. Here you can enable pipelines for the repo.
  2. Next, under the Pipeline settings navigate to Repository Variables. Here you can add variables to be used within your deployment pipeline.
  3. You need to set variables to allow Pipelines access to your AWS account. Set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION. These value should come from an IAM user with enough permissions to write to S3.
  4. Next add a bitbucket-pipelines.yml file to your repo. Below is an example file, to learn more about how to setup a pipelines yml file please check it out here. The below file handles a number of things:
  • Any pushes to the Dev branch will automatically run the application tests.
  • The script has two manual deployment steps, one for staging and one for production. Each step handles: testing the app, building our React bundle and using a Bitbucket Pipe to push the bundle to the S3 bucket that was created. Notice in the pipe we specify the S3 bucket name. This variable can also be set in the Repository Variables.
image: node:10.15.3

pipelines:
custom: # Pipelines that can only be triggered manually
staging:
- step:
name: Installing & Running Tests
caches:
- node
script:
- rm -rf package-lock.json
- rm -rf node_modules
- npm install
- npm run test
- step:
name: Build
script:
- npm install --production
- REACT_APP_ENVIRONMENT=staging npm run build
artifacts:
- build/**
- step:
name: Deploy to S3
deployment: staging
script:
- pipe: atlassian/aws-s3-deploy:0.2.4
variables:
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
S3_BUCKET: $STAGING_BUCKET_NAME
ACL: "public-read"
LOCAL_PATH: "build"
- step:
name: Invalidate Cloudfront Cache
script:
- pipe: atlassian/aws-cloudfront-invalidate:0.1.1
variables:
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
DISTRIBUTION_ID: $STAGING_DISTRIBUTION_ID
production:
- step:
name: Installing & Running Tests
caches:
- node
script:
- rm -rf package-lock.json
- rm -rf node_modules
- npm install
- npm run test
- step:
name: Build
script:
- npm install --production
- REACT_APP_ENVIRONMENT=production npm run build
artifacts:
- build/**
- step:
name: Deploy to S3
deployment: production
script:
- pipe: atlassian/aws-s3-deploy:0.2.4
variables:
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
S3_BUCKET: $PRODUCTION_BUCKET_NAME
ACL: "public-read"
LOCAL_PATH: "build"
- step:
name: Invalidate Cloudfront Cache
script:
- pipe: atlassian/aws-cloudfront-invalidate:0.1.1
variables:
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
DISTRIBUTION_ID: $PRODUCTION_DISTRIBUTION_ID
branches:
dev:
- step:
name: Installing & Running Tests
caches:
- node
script:
- rm -rf package-lock.json
- rm -rf node_modules
- npm install
- npm run test

5. Once these files are committed to the repository you are ready to do a deployment!

Enjoy!

I hope this walk through will save you some time and get you started on creating your CI/CD pipeline with Bitbucket Pipelines and Amazon S3. If you have any questions please leave a comment.

--

--