AWS Mobile Blog

Deploying a Static Website with AWS Amplify and CDK

This post was written by Ozioma Uzoegwu, Solution Architect at AWS.

In this blog post, we will build a sample React application that will be hosted on AWS Amplify. This can be done directly using the Amplify Console, however we will be using AWS Cloud Development Kit (AWS CDK) to show how to develop the infrastructure and the configurations required to host the application on Amplify.

Deploying infrastructure with AWS CDK will enable DevOps teams to: standardize infrastructure components; deploy in a repeatable manner and develop with familiar programming language. Managed Service Providers that offer website hosting services will also benefit from an automated deployment and management of multiple Amplify applications across various customers.

Overview of the AWS Amplify and AWS CDK

AWS Amplify provides developers with a set of tools and services to build secure and scalable full stack cloud applications. One of the tools is the AWS Amplify Console that provides a GUI with a git-based workflow for hosting static sites as well as full stack serverless web applications. Applications can be deployed by connecting to an existing repository (GitHub, BitBucket Cloud, GitLab and AWS CodeCommit) to set up a fully managed continuous deployment pipeline. Subsequently, any changes committed to the repository will trigger the pipeline to build, test and deploy the changes to the target environment. It also provides instant content delivery network (CDN) cache invalidation, atomic deploys, password protection, and redirects without the need to manage any servers.

AWS CDK is an open source software development framework which can be used to model and provision your cloud application resources using familiar programming languages, including TypeScript, JavaScript, Python, C# and Java. For the example in this blog, we will be using Typescript.

The figure below shows the AWS services and the steps involved in deploying the sample React application using Amplify and CDK.

  1. Build static websites or the frontend of a full stack application and commit the code to any of the repositories GitLab, GitHub (1a) or AWS CodeCommit (1b). Note: Creating Amplify application from source code in BitBucket is not currently supported using CDK. To connect to a BitBucket repository use the Amplify console.
  2. Setup AWS CDK with a familiar programming language. Build and deploy the CDK code to the target AWS region to create the Amplify application.
  3. The CDK code will be converted to a CloudFormation template which will be deployed in the target region to create the Amplify Application.
  4. Any subsequent commits will trigger the Amplify continuous deployment pipeline which will fork the code from the configured repository (4a). For GitLab and GitHub, AWS Secrets Manager can be used to store the personal access token (4b) which provides Amplify the permission to access the repository.
  5. Amplify will generate a shareable URL which can be used to access the application from the internet. It also provides the flexibility of configuring a custom domain with SSL certificates issued by Amplify.

Prerequisites

To deploy the sample application with CDK, the following will need to be setup:

  • Node Package Manager (NPM), follow the instructions here to install.
  • AWS CLI installed and configured with administrator privileges

Install the AWS CDK Toolkit

The AWS CDK Toolkit, the CLI command cdk, is the primary tool for interacting with your AWS CDK app. It will be used to deploy the CDK code to the target AWS environment. To install, use the command below.

npm install -g aws-cdk

Creating a sample ReactJS App

The below command will create a new project folder (amplify-react-sample) which will contain the React app and the CDK app. It will also create a sample React application which is launched in localhost as shown in the figure below.

npx create-react-app amplify-sample-app
cd amplify-sample-app
npm start

Building the infrastructure with AWS CDK

The below command creates the CDK app which will be developed in Typescript. The CDK app will be stored in the new folder amplify-infra. The typescript code for the cdk app will be defined in the file amplify-infra-stack.ts which is in the lib folder of the CDK application (amplify-react-sample/amplify-infra/lib/amplify-infra-stack.ts).

cd ~/amplify-sample-app
mkdir amplify-infra
cd amplify-infra
cdk init --language typescript

To install the CDK modules required to build the application, run the following commands

npm install @aws-cdk/aws-codecommit @aws-cdk/aws-amplify

It is recommended that the version of the installed modules is the same as the version of the cdk core module. To implement this, identify the version of the installed @aws-cdk/core module (from the package.json file) and add the value to the install command of any new module. For example, npm install @aws-cdk/aws-codecommit@X.XX.X

Creation of the source control repository (optional)

Currently, CDK provides the option of using GitHub, GitLab and AWS CodeCommit as the source repository. For this example, CodeCommit is used as the source repository and the repository is created using CDK.

// ~/amplify-react-sample/amplify-infra/lib/amplify-infra-stack.ts

import * as cdk from "@aws-cdk/core";
import * as codecommit from "@aws-cdk/aws-codecommit";

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

    // Part 1 [Optional] - Creation of the source control repository
    const amplifyReactSampleRepo = new codecommit.Repository(
      this,
      "AmplifyReactTestRepo",
      {
        repositoryName: "amplify-react-test-repo",
        description:
          "CodeCommit repository that will be used as the source repository for the sample react app and the cdk app",
      }
    );
  }
}

To build the application and deploy the resources to AWS cloud, run the following commands:

cd ~/amplify-sample-app/amplify-infra	
npm run build
cdk deploy

This will create the CodeCommit repository which can be used as the source repository for the sample React app and cdk app. Commit the “amplify-sample-app” folder (which contains the sample React app and the cdk code) to the repository using standard git commands.

Creation of the Amplify Application

CDK provides a construct App to define and configure an Amplify application. The sample code below shows an example of an Amplify Application created from a source code in CodeCommit. The build specification to define the actions to be performed during the automated Amplify build stage can be defined by adding “amplify.yml” to the repository (~/amplify-sample-app/amplify.yml). A sample content of the file as used in this example is shown below.

// ~/amplify-react-sample/amplify-infra/lib/amplify-infra-stack.ts

import * as cdk from "@aws-cdk/core";
import * as codecommit from "@aws-cdk/aws-codecommit";
import * as amplify from "@aws-cdk/aws-amplify";

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

    // Part 1 [Optional] - Creation of the source control repository
    const amplifyReactSampleRepo = new codecommit.Repository(
      this,
      "AmplifyReactTestRepo",
      {
        repositoryName: "amplify-react-test-repo",
        description:
          "CodeCommit repository that will be used as the source repository for the sample react app and the cdk app",
      }
    );

    // Part 2 - Creation of the Amplify Application
    const amplifyApp = new amplify.App(this, "sample-react-app ", {
      sourceCodeProvider: new amplify.CodeCommitSourceCodeProvider({
        repository: amplifyReactSampleRepo,
      }),
    });
    const masterBranch = amplifyApp.addBranch("master");
  }
}

version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: build
    files:
      - "**/*"
  cache:
    paths:
      - node_modules/**/*

Amplify application can also be created from a code base in GitHub repository. CDK provides a class GitHubSourceCodeProvider within the @aws-cdk/aws-amplify package which enables an amplify application to be created by specifying the repository owner, name and a personal access token. The token will need to be granted the “repo” scope to give amplify the necessary permission to access the repository. For example, amplify will create a webhook in the GitHub repository which will be triggered when one or more commits are pushed to a repository branch or tag. In the code example below, the token generated is stored encrypted as a key-value pair in AWS Secrets Manager and will be retrieved at runtime to access the GitHub repository.

// ~/amplify-react-sample/amplify-infra/lib/amplify-infra-stack.ts

import * as cdk from "@aws-cdk/core";
import * as amplify from "@aws-cdk/aws-amplify";

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

    // Part 2 - Creation of the Amplify Application
    const amplifyApp = new amplify.App(this, "sample-react-app ", {
      sourceCodeProvider: new amplify.GitHubSourceCodeProvider({
        owner: "[Repository-Owner]",
        repository: "[Repository-Name]",
        oauthToken: cdk.SecretValue.secretsManager("[Secret-Name]", {
          jsonField: "[Secret-Key]",
        }),
      }),
    });
    const masterBranch = amplifyApp.addBranch("master");
  }
}

Ensure to replace the following placeholders [Repository-Owner] and [Repository-Name] from GitHub; [Secret-Name] and [Secret-Key] from AWS Secrets Manager

Rebuild and deploy the cdk application to create the Amplify application with the instruction below.

cd ~/amplify-sample-app/amplify-infra	
npm run build
cdk deploy

Testing

New commits to the repository will automatically trigger the Amplify continuous deployment pipeline to deploy the changes to the application. To test this with the sample React application, make changes to the text displayed on the landing page of the React App by modifying the “App.js” file under the “src” folder. For example, modify the text “Learn React” to “Testing Amplify Deployment via CDK” and commit the changes to the repository. This should trigger the Amplify pipeline with the changes reflected on the portal as show below.

When you view your live domain, you should now see these updates reflected.

Similar implementations are provided for GitLab which can be configured using the Amplify class GitLabSourceCodeProvider. Other features of an amplify App that can be configured via CDK include adding customer rules for redirection; adding a domain and mapping sub domains to branches; adding environment variable. For more details on how to leverage these features refer to the amplify App construct.

Next Steps

Deploying infrastructure with AWS CDK enables the automated testing of the infrastructure code as part of the development process. AWS provides a Testing Construct for CDK applications written in Typescript language with the intention to support other languages sometime in the future. Amplify provides the ability to integrate a frontend application with backend functionality using Amplify Javascript Libraries, for example adding a REST or GraphQL API, Authentication and many other services. To add a backend to your application, follow the guide here.

To clean up the sample project, run the command cdk destroy to delete the cloud resources.

Conclusion

In this blog post, we have covered the steps to get started in deploying an Amplify Application using AWS CDK which can be extended to build a full stack application using Amplify CLI and Amplify Libraries. AWS Amplify and AWS CDK are both open source project and we will welcome any feedback or feature request which can be raised in the Amplify Github repository and  CDK Github repository respectively. To learn more about the Amplify and CDK, you can read the Amplify documentation and the CDK documentation.