cdk-spa

AWS CDK stack to deploy single page applications (SPA) and static site generators (SSG) on S3 and CloudFront

APACHE-2.0 License

Downloads
284
Stars
0
Committers
1

CDK-SPA

Install any client-only SPA (single page application) on AWS with automatic deployment.

  • Fast responses from CloudFront
  • Automatic upload of the build files for CSR and static assets to S3 with optimized caching rules
  • Automatic build and deploy with CodeBuild and CodePipeline from Github repository.
  • Publicly available by a custom domain (or subdomain) via Route53

Prerequisites

You need an AWS account to create and deploy the required resources for the site on AWS.

This package uses the npm package manager and is an ES6+ Module.

Installation

Install the package and its required dependencies:

npm i @thunderso/cdk-spa --save-dev

Your package.json must also contain tsx and this specific version of aws-cdk-lib :

npm i tsx [email protected] --save-dev

Setup

  1. Login into the AWS console and note the Account ID. You will need it in the configuration step.

  2. Run the following command to automatically create the required CDK stack entrypoint at stack/index.ts. This file defines the config how the app will be deployed via CDK. You should adapt the file to the project's needs, especially the props env.account (setup step 1).

npx cdk-spa-init 

Enable Automatic Deployments

  1. Create a Github Personal Access Token for your Github account. This token must be kept secure.

  2. Create a Secrets Manager secret as plaintext with the Personal Access Token you created earlier. Note the ARN of the secret. E.g. arn:aws:secretsmanager:<REGION_NAME>:<ACCOUNT_ID>:secret:<secret-name>.

  3. Input the noted ARN to the githubAccessTokenArn field in your stack.

Manage Domain with Route53 (Optional)

  1. Create a hosted zone in Route53 for the desired domain, if you don't have one yet.

This is required to create DNS records for the domain to make the app publicly available on that domain. On the hosted zone details you should see the Hosted zone ID of the hosted zone.

  1. Request a public global certificate in the AWS Certificate Manager (ACM) for the desired domain in us-east-1 (global) and validate it, if you don't have one yet.

This is required to provide the app via HTTPS on the public internet. Take note of the displayed ARN for the certificate.

[!IMPORTANT] The certificate must be issued in us-east-1 (global) regardless of the region used for the app itself as it will be attached to the CloudFront distribution which works globally.

Configuration

The SPAStack construct can be configured via the following props:

Deployment

After the installation and the setup you are already good to go to build the app and to deploy it to AWS with this package by following the steps below:

1. Bootstrap CDK

Deploying stacks with the AWS CDK requires dedicated Amazon S3 buckets and other containers to be available to AWS CloudFormation during deployment. Creating these is called bootstrapping and is only required once per account and region. To bootstrap, run the following command:

cdk bootstrap aws://ACCOUNT-NUMBER/REGION

See https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html for details.

2. Build and Deploy

By running the following script, the CDK stack will be deployed to AWS.

npx cdk deploy --require-approval never --all --app="npx tsx stack/index.ts" 

Destroy the Stack

If you want to destroy the stack and all its resources (including storage, e.g., access logs), run the following script:

npx cdk destroy --require-approval never --all --app="npx tsx stack/index.ts" 

Reference: Created AWS Resources

In the following, you can find an overview of the AWS resources that will be created by this package for reference.

SPAStack

This stack is responsible for deploying static sites and dynamic SPA apps to AWS. The following AWS resources will be created by this stack:

  • CloudFront: A distribution to route incoming requests to the S3 bucket to serve the static assets for the app.

  • S3: A bucket to store the client files and static assets of the build with optimized cache settings.

  • CodeBuild: A build project to automatically build and package the static assets from the source code.

  • CodePipeline: A deployment pipeline to automate the release process, integrating with CodeBuild, S3, and other AWS services.

  • Route53: Two DNS records (A for IPv4 and AAAA for IPv6) in the configured hosted zone to make the app available on the internet via the configured custom domain.

Manually setting up CDK

You can use SPAStack as a CDK construct within your CDK code to seamlessly integrate hosting. Here's an example of how to use it:

Create a stack directory in your project root and an empty file index.ts and fill in the props accordingly.

Use different filenames such as production.ts and testing.ts for environments.

import { App } from "aws-cdk-lib";
import { SPAStack, type SPAProps } from "@thunderso/cdk-spa";

const appStackProps: SPAProps = {
  env: {
    account: 'your-account-id',
    region: 'us-east-1'
  },
  application: 'your-application-id',
  service: 'your-service-id',
  environment: 'production',

  // Your Github repository url contains https://github.com/<owner>/<repo>
  sourceProps: {
    owner: 'your-github-username',
    repo: 'your-repo-name',
    branchOrRef: 'main',
    rootdir: ''
  },

  // Auto deployment
  // - create a Github personal access token
  // - store in Secrets Manager as plaintext
  githubAccessTokenArn: 'arn:aws:secretsmanager:us-east-1:123456789012:secret/github-token',

  // Either provide a buildspec.yml file OR fill out buildProps
  // - providing a buildspec.yml will override buildProps and sourceProps.rootdir
  // buildSpecFilePath: 'stack/buildspec.yml',
  buildProps: {
    runtime: 20, // nodejs versions 16, 18 and 20 supported
    installcmd: 'npm ci',
    buildcmd: 'npm run build',
    outputDir: 'dist/'
  },

  // Custom CloudFront Functions for URL rewrite
  edgeFunctionFilePath: 'stack/urlrewrite.js',

  // Optional: Domain settings
  // - create a hosted zone for your domain
  // - issue a global tls certificate in us-east-1 
  domain: 'sub.example.com',
  hostedZoneId: 'Z1D633PJRANDOM',
  globalCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/abcd1234-abcd-1234-abcd-1234abcd1234',

  // all resources created in the stack will be tagged
  // tags: {
  //   key: 'value'
  // },
};

new SPAStack(new App(), `${appStackProps.application}-${appStackProps.service}-${appStackProps.environment}-stack`, appStackProps);

Run the following command to deploy stack.

npx cdk deploy --require-approval never --all --app="npx tsx stack/index.ts" 

Advanced

Cloudfront edge functions can be used for URL rewrite, among other use-cases.

[!NOTE] Check out the resources from aws-samples/amazon-cloudfront-functions for examples.

Useful commands

  • npx cdk deploy deploy this stack to your default AWS account/region
  • npx cdk diff compare deployed stack with current state
  • npx cdk synth emits the synthesized CloudFormation template