How to deploy a React web app in AWS S3 Using AWS CDK and AWS CodeStar

Joel Wembo
Towards AWS
Published in
13 min readApr 3, 2024

--

AWS CodeStar enables you to quickly develop, build, and deploy applications on AWS. AWS CodeStar provides a unified user interface, enabling you to easily manage your software development activities in one place. With AWS CodeStar, you can set up your entire continuous delivery toolchain in minutes, allowing you to start releasing code faster.

React web app in AWS S3 Using AWS CDK and AWS CodeStar Architecture

AWS CodeStar makes it easy for your whole team to work together securely, allowing you to easily manage access and add owners, contributors, and viewers to your projects. Each AWS CodeStar project comes with a project management dashboard, including an integrated issue tracking capability powered by Atlassian JIRA Software. With the AWS CodeStar project dashboard, you can easily track progress across your entire software development process, from your backlog of work items to teams’ recent code deployments. Visit here to learn more.

AWS CodeStar with Github for CI/CD

In this blog, will guide you build a CI CD Pipeline (CodePipeline, Code Build and CodeDeploy) for a Static React Website using AWS CDK . All the web contents will be compiled first front React application , the build artifacts will be pushed to AWS S3 automatically using AWS CodeStar, which establish connection between your github repositories and aws CodePipeline.

Prerequisites:

Before we get into the good stuffs, first we need to make sure we have the required services on our local machine or dev server, which are:

  1. Basic knowledge of Django and AWS CDK.
  2. AWS Account
  3. Github Account
  4. AWS CLI installed and configured.
  5. Docker installed locally.
  6. AWS CDK installed.
  7. Typescript installed
  8. Postman
  9. Python 3
  10. NPM
  11. NodeJS
  12. A Domain name Hosted from any domain name provider ( Ex: AWS Route 53 )
  13. Basic knowledge of HTML and React
  14. Any Browser for testing

Quick Explanation on CodePipeline

AWS CodePipeline is a fully managed continuous integration and continuous delivery (CI/CD) service provided by Amazon Web Services (AWS). It enables users to automate the build, test, and deployment processes of their software applications and infrastructure updates.

Pipeline: A pipeline is a workflow that defines the stages and actions to be executed in sequence for building, testing, and deploying code changes. Each stage in the pipeline represents a phase of the software delivery process, such as source code retrieval, build, test, and deployment.

Stages: Stages are the logical divisions within a pipeline. Each stage typically represents a distinct phase of the software delivery process, such as building, testing, or deploying code changes.

Actions: Actions are the individual tasks or operations performed within each stage of the pipeline. AWS CodePipeline provides various built-in actions for common tasks like source code retrieval from AWS CodeCommit, GitHub, or Amazon S3, as well as actions for building code using AWS CodeBuild, deploying code to AWS Elastic Beanstalk, AWS Lambda, Amazon ECS, or AWS Fargate, and executing custom scripts.

Why S3 ?

Amazon S3 gives every user, its service access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of websites. S3 Standard is designed for 99.99% availability and Standard — IA is designed for 99.9% availability.

Why AWS CDK ?

AWS CDK provides a library of constructs that cover many AWS services and features, enabling you to define your applications’ infrastructure at a high level. we are going to use aws cdk to define both resources and functions to manage all needed services from declaring the s3 to the releasing of codes to AWS Codebuild.

1. Setup React application

React is a free and open-source front-end JavaScript library for building user interfaces based on components. It is maintained by Meta and a community of individual developers and companies. React can be used to develop single-page, mobile, or server-rendered applications with frameworks like Next.js.

Step 1 : Create your React Application:

To start, Create your repository in github account as follow :

Make sure you upload the changes in your react web UI repository as we will host the infrastructure as code (cdk and CloudFormation) in a different repository.

Create React App is a comfortable environment for learning React, and is the best way to start building a new single-page application in React.

let sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production. You’ll need to have Node >= 14.0.0 and npm >= 5.6 on your machine. To create a project, run:

npx create-react-app prodx-reactwebui-react-demo-1
cd prodx-reactwebui-react-demo-1
npm start

To get ahead, You can download the source code here:

Step 2: Create a Production Build of your application

Let build static contents to serve in AWS S3 Static Web Hosting

npm run build

The above command creates a build directory with a production build of your app. Set up your favorite HTTP server so that a visitor to your site is served index.html, and requests to static paths like /static/js/main.<hash>.js are served with the contents of the /static/js/main.<hash>.js file.

the generated build folder contains the index.html to serve in s3
React App Build result
React and build folder project structure

Step 3: Test the application locally

The generated build folder contains the index.html to serve in aws s3 static web hosting, run the command server to test the build contents for production release.


serve -s build

Run the command server to test the build contents for production release. We are going to need the build files for our next part , where terraform will upload these contents to s3 using infrastructure as code.

serving production files in local computer
Testing react application locally
running react application ready for production release

2. Setup CodeStar Connection

You use connections to authorize and establish configurations that associate your third-party provider with your AWS resources.

Use these steps to use the CodePipeline console to add a connections action for your GitHub or GitHub Enterprise Cloud repository.

Step 1: Create or edit your pipeline

  1. Sign in to the CodePipeline console.
  2. Choose one of the following.
  • Choose to create a pipeline. Follow the steps in Create a Pipeline to complete the first screen and choose Next. On the Source page, under Source Provider, choose GitHub (Version 2).
  • Choose to edit an existing pipeline. Choose Edit, and then choose Edit stage. Choose to add or edit your source action. On the Edit action page, under Action name, enter the name for your action. In Action provider, choose GitHub (Version 2).

3. Do one of the following:

  • Under Connection, if you have not already created a connection to your provider, choose Connect to GitHub. Proceed to Step 2: Create a Connection to GitHub
  • Under Connection, if you have already created a connection to your provider, choose the connection. Proceed to Step 3: Save the source action for your connection.

Step 2: Create a connection to GitHub

After you choose to create the connection, the Connect to GitHub page appears.

  1. Under GitHub connection settings, your connection name appears in Connection name. Choose Connect to GitHub. The access request page appears.
  2. Choose Authorize AWS Connector for GitHub. The connection page displays and shows the GitHub Apps field.
  1. Under GitHub Apps, choose an app installation or choose Install a new app to create one.
  2. You install one app for all of your connections to a particular provider. If you have already installed the AWS Connector for GitHub app, choose it and skip this step.
  3. On the Install AWS Connector for GitHub page, choose the account where you want to install the app.
  4. You only install the app once for each GitHub account. If you previously installed the app, you can choose Configure to proceed to a modification page for your app installation, or you can use the back button to return to the console.
  5. On the Install AWS Connector for GitHub page, leave the defaults, and choose Install.
  6. On the Connect to GitHub page, the connection ID for your new installation appears in GitHub Apps. Choose Connect.
AWS Connector for Github
Successful Connection with github and aws

3. Setup the infrastructure as code deployment solution using aws cdk

The AWS Cloud Development Kit is an open-source software development framework developed by Amazon Web Services for defining and provisioning cloud infrastructure resources using familiar programming languages.

To Set up your AWS CDK project use the following steps

  • Install NodeJS
  • Install typescript
  • install aws-cdk using NPM

Initialize the project using typescript

cdk init app --language typescript

Open your IDE #

Now’s a good time to open the project in your favorite IDE and explore.

If you use VSCode, you can just type code . within the project directory.

Explore your project directory #

You’ll see something like this:

  • package.json is your npm module manifest. It includes information like the name of your app, version, dependencies and build scripts like “watch” and “build” (package-lock.json is maintained by npm)
  • cdk.json tells the toolkit how to run your app. In our case it will be "npx ts-node bin/entrypoint.ts"
  • tsconfig.json your project’s typescript configuration
  • .gitignore and .npmignore tell git and npm which files to include/exclude from source control and when publishing this module to the package manager.
  • node_modules is maintained by npm and includes all your project’s dependencies.

4. cloud-infra-stack.ts

Next, we need to define the Cloud Infrastructure stack using typescript to handle the complete deployment using CI/CD toolkit within aws.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as CodeBuild from 'aws-cdk-lib/aws-codebuild';
import * as CodePipeline from 'aws-cdk-lib/aws-codepipeline';
import * as CodePipelineAction from 'aws-cdk-lib/aws-codepipeline-actions'
// import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
import { BlockPublicAccess, BucketAccessControl } from 'aws-cdk-lib/aws-s3';
import { CfnOutput, Duration, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';

export class CloudInfraStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// TO DO: Please replace the s3 Bucket name to a unique name of your choice.

const websiteBucket = new s3.Bucket(this, 'prodx-reactwebui-react-demo-6', {
bucketName: "prodxreactwebuireactdemo",
publicReadAccess: true,
removalPolicy: RemovalPolicy.DESTROY,
// autoDeleteObjects: true,
blockPublicAccess: BlockPublicAccess.BLOCK_ACLS,
accessControl: BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
websiteIndexDocument: 'index.html',
websiteErrorDocument: 'error.html'

})

new CfnOutput(this, 'Bucket', { value: websiteBucket.bucketName });

const outputSource = new CodePipeline.Artifact();
const outputWebsite = new CodePipeline.Artifact();

const pipeline = new CodePipeline.Pipeline(this, "Pipeline", {
pipelineName: "ReactStaticWebCICDPipeline",
restartExecutionOnUpdate: true,
});

// TO DO: Please replace the connectionArn value with your codestar connection arn
pipeline.addStage({
stageName: "Source",
actions: [
new CodePipelineAction.CodeStarConnectionsSourceAction({
actionName: "Github_Source",
owner: "joelwembo",
repo: "prodx-reactwebui-react-demo-1",
branch: "main",
output: outputSource,
connectionArn: "",
})
]
});

pipeline.addStage({
stageName: "Build",
actions: [
new CodePipelineAction.CodeBuildAction({
actionName: "Build-UI",
project: new CodeBuild.PipelineProject(this, "UIBuild", {
environment: {
buildImage: CodeBuild.LinuxBuildImage.AMAZON_LINUX_2_4,
privileged: true,
computeType: CodeBuild.ComputeType.SMALL,
},
projectName: "StaticWebsiteBuild",
buildSpec: CodeBuild.BuildSpec.fromSourceFilename("./buildspec.yml"),
}),
input: outputSource,
outputs: [outputWebsite]
})
],
});

pipeline.addStage({
stageName: "Deploy",
actions: [
new CodePipelineAction.S3DeployAction({
actionName: "DeployingStaticWebsite",
input: outputWebsite,
bucket: websiteBucket,
})
]
});
}
}

let explain few part of the code !!

// TO DO: Please replace the s3 Bucket name to a unique name of your choice.

const websiteBucket = new s3.Bucket(this, 'prodx-reactwebui-react-demo-6', {
bucketName: "prodxreactwebuireactdemo",
publicReadAccess: true,
removalPolicy: RemovalPolicy.DESTROY,
// autoDeleteObjects: true,
blockPublicAccess: BlockPublicAccess.BLOCK_ACLS,
accessControl: BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
websiteIndexDocument: 'index.html',
websiteErrorDocument: 'error.html'

})

The s3 construct code above provision the s2 buckets with permissions and policy where our website contents will be uploaded.

The code below will create CodePipeline where the artifacts of build will be pushed to

const pipeline = new CodePipeline.Pipeline(this, "Pipeline", {
pipelineName: "ReactStaticWebCICDPipeline",
restartExecutionOnUpdate: true,
});

To establish connation between aws CodePipeline and github we used the following code :

// TO DO: Please replace the connectionArn value with your codestar connection arn
pipeline.addStage({
stageName: "Source",
actions: [
new CodePipelineAction.CodeStarConnectionsSourceAction({
actionName: "Github_Source",
owner: "joelwembo",
repo: "prodx-reactwebui-react-demo-1",
branch: "main",
output: outputSource,
connectionArn: "arn:aws:codestar-connections:us-east-1:059978233428:connection/395a5682-d574-47af-bb99-98f1f5aa0ce1",
})
]
});

The CodeStar Connections will also depend on the connection Arn defined during code pipelines settings that we did already during code start configuration.

Last, if the build is successful, the following code will trigger to upload of the react production ready build to aws s3 :

pipeline.addStage({
stageName: "Deploy",
actions: [
new CodePipelineAction.S3DeployAction({
actionName: "DeployingStaticWebsite",
input: outputWebsite,
bucket: websiteBucket,
})
]
});

5. Define buildspec.yaml in react

A buildspec is a collection of build commands and related settings, in YAML format, that CodeBuild uses to run a build. You can include a buildspec as part of the source code or you can define a buildspec when you create a build project. For information about how a build spec works, see How CodeBuild works.

Next, we need to define buildspec.yaml in root directory of our react application to build the app as show in screenshot below:

version: 0.2

phases:
install:
runtime-versions:
nodejs: 16
commands:
- npm install
build:
commands:
- npm run build
artifacts:
base-directory: ./build
files:
- '**/*'
buildspec.yaml inside react application for CI/CD Compilation

6. Test your solution

Let deploy the cdk stack using the following commands

npm run build
cdk synth
export CDK_NEW_BOOTSTRAP=1
cdk bootstrap --trust=YOUR-AWS-ACCOUNT aws://YOUR-AWS-ACCOUNT/us-east-1 --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess aws://YOUR-AWS-ACCOUNT/us-east-1 --verbose --profile=default
cdk deploy --force --method=direct --require-approval never --no-previous-parameters --verbose --profile=default

7. Check result in your AWS Management Console

AWS CodeBuild Progress
Build Progress during git changes

Check the s3 bucket directories to see if our website was uploaded successfully.

AWS S3 hosting will generate a unique URL for our react web application

Static website hosting using s3
Website deployed using aws cdk

Summary

This completes all of the necessary steps for deploying a secured static website on AWS using AWS CodeStar, CodePipeline and AWS CDK to AWS S3 bucket.

Here are some benefits of using AWS CodeStar:

  1. Integrated Development Environment (IDE): CodeStar provides an integrated development environment that allows developers to easily manage and collaborate on their code within the AWS ecosystem. This integrated environment includes tools for code editing, debugging, and version control.
  2. Project Templates: CodeStar offers project templates for various programming languages and frameworks, making it easy to start new projects quickly. These templates come pre-configured with AWS services such as AWS Lambda, Amazon S3, AWS CodeCommit, AWS CodeBuild, and AWS CodePipeline, reducing the setup time for new projects.
  3. Automated Provisioning: CodeStar automates the provisioning of the necessary AWS resources for your project, such as compute instances, databases, and storage. This eliminates the need for manual setup and configuration, saving time and reducing the risk of errors.
  4. Continuous Integration/Continuous Deployment (CI/CD): CodeStar integrates with AWS CodePipeline to automate the build, test, and deployment process for your applications. This CI/CD pipeline helps teams deliver changes to production faster and more reliably.
  5. Team Collaboration: CodeStar provides features for team collaboration, including built-in project management tools and integration with third-party collaboration tools such as Slack and JIRA. This fosters better communication and coordination among team members.
  6. Built-in Monitoring and Metrics: CodeStar integrates with AWS CloudWatch to provide built-in monitoring and metrics for your applications. This allows you to easily monitor the health and performance of your applications and respond quickly to any issues that arise.
  7. Security and Compliance: CodeStar leverages AWS Identity and Access Management (IAM) to manage user permissions and access controls for your projects. It also provides features for encryption, compliance, and auditing to help you maintain the security and compliance of your applications.
  8. Scalability and Flexibility: As with other AWS services, CodeStar offers scalability and flexibility, allowing you to easily scale your projects as needed and adapt to changing requirements without having to worry about infrastructure management.

Overall, AWS CodeStar helps teams accelerate the development process, improve collaboration, and deliver high-quality software more efficiently by providing a fully managed development environment with integrated tools and automation.

“Programming is not a zero-sum game. Teaching something to a fellow programmer doesn’t take it away from you.” John Carmack

You can download both the front-end and the infrastructure as code here:

Thank you for Reading , see you in the next article !

References

--

--

I am a Cloud Solutions Architect, I provide IT solutions using AWS, AWS CDK, Kubernetes, Serverless and Terraform. https://www.linkedin.com/in/joelotepawembo