Building and Deploying a Simple Website on AWS with Lambda, S3, and CDK TypeScript

Hi, this is Charu from Classmethod. In this blog we'll explore how to deploy a simple website using AWS CDK, TypeScript language.

Let's get started!

Install AWS CDK and initialise your CDK app using the following two commands-

npm install -g aws-cdk
cdk init app --language=typescript

Let's make the AWS resources using AWS CDK. To deploy a simple website, we will be making a Lambda function, S3 bucket and an API.

The CDK Typescript code to make the above resources is written below. You are free to change the resource/stack names.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  aws_lambda,
  aws_s3,
  aws_lambda_nodejs,
  aws_apigateway,
  aws_s3_deployment,
} from "aws-cdk-lib";

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

    const websiteBucket = new aws_s3.Bucket(this, "WebsiteBucket", {
      websiteIndexDocument: "index.html",
    });

    new aws_s3_deployment.BucketDeployment(this, "DeployWebsite", {
      sources: [aws_s3_deployment.Source.asset("src/web")],
      destinationBucket: websiteBucket,
    });


    const lambdaFunction = new aws_lambda_nodejs.NodejsFunction(
      this,
      "LambdaFunction",
      {
        runtime: aws_lambda.Runtime.NODEJS_18_X,
        entry: "src/lambda/websiteLambda/index.ts",
        architecture: aws_lambda.Architecture.ARM_64,
      }
    );

    const api = new aws_apigateway.RestApi(this, "MyApi", {
      restApiName: "MyApi",
    });

    const integration = new aws_apigateway.LambdaIntegration(lambdaFunction);
    const resource = api.root.addResource("myresource");
    resource.addMethod("GET", integration);
  }
}

You can make a simple lambda code under src/lambda folder as shown below-

export const handler = async (): Promise<any> => {
  return {
    statusCode: 500,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": true,
      "Access-Control-Allow-Headers": "Content-Type",
      "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
    },
    body: JSON.stringify({ message: "Hello from Lambda!" }),
  };
};

Below is the index.html code. You can write this code under src/web folder,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My AWS Website</title>
</head>
<body>
    <h1 id="greeting">Loading...</h1>
    <script>
        fetch('YOUR-API-ENDPOINT')
            .then(response => response.json())
            .then(data => {
                document.getElementById('greeting').innerText = data.message;
            })
            .catch(error => console.error('Error:', error));
    </script>
</body>
</html>

Now, you can check your website through S3 bucket URL. It should display 'Hello from Lambda!' like this,

Conclusion:

Congratulations, you just deployed your website in AWS. In summary, your HTML file is hosted in S3 that interacts with the API Gateway endpoint, which, in turn, triggers the Lambda function. The Lambda function processes the request and sends a response back to the client, allowing dynamic interaction between your static HTML content and serverless backend logic.

Happy Learning:)