Skip to main content

CloudFront CDN

Next we'll setup a CDN for the site using AWS CloudFront, so the site loads fast everywhere in the world.

The most basic CDN setup for an S3 static website is:

new cloudfront.Distribution(this, "CDN", {
defaultBehavior: {
origin: new origins.S3StaticWebsiteOrigin(websiteBucket),
},
});

Update the CDK Stack to configure CloudFront for the site's S3 bucket (new changes are highlighted):

aws-infra/lib/aws-infra-stack.ts
import * as cdk from "aws-cdk-lib";
import type { Construct } from "constructs";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as s3deploy from "aws-cdk-lib/aws-s3-deployment";
import { execSync } from "node:child_process";
// add cloudfront imports:
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";

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

const websiteDir = `${__dirname}/../..`;

console.log("Building the website for deployment...");
execSync("npm run build", { cwd: websiteDir, stdio: "inherit" });

const websiteBucket = new s3.Bucket(this, "Bucket", {
websiteIndexDocument: "index.html",
websiteErrorDocument: "404.html",
publicReadAccess: true,
blockPublicAccess: {
blockPublicPolicy: false,
blockPublicAcls: false,
ignorePublicAcls: false,
restrictPublicBuckets: false,
},
});

// create a CloudFront distribution:
const cdn = new cloudfront.Distribution(this, "CDN", {
defaultBehavior: {
origin: new origins.S3StaticWebsiteOrigin(websiteBucket),
},
});

new s3deploy.BucketDeployment(this, "Deploy", {
sources: [s3deploy.Source.asset(`${websiteDir}/build`)],
destinationBucket: websiteBucket,
// set this to invalidate the CDN cache and serve the latest files:
distribution: cdn,
});

new cdk.CfnOutput(this, "S3BucketUrl", {
value: websiteBucket.bucketWebsiteUrl,
});

// output the CDN URL
new cdk.CfnOutput(this, "CdnUrl", {
value: `https://${cdn.domainName}`,
});
}
}

Deploy that with cdk deploy. The first time it can take a while (maybe 5-10 minutes). If it succeeded it should output something like:

 ✅  SiteOnAws

✨ Deployment time: 453.83s

Outputs:
SiteOnAws.CdnUrl = https://d3vsjivg0zb3wu.cloudfront.net
SiteOnAws.S3BucketUrl = ...

Open that CDN URL in a browser and the site should load.

warning

If you forget to add the distribution: cdn prop to the s3deploy.BucketDeployment, even if the deploy succeeds, you won't see any changes because the old content is still cached on the CDN. If you keep seeing old content, make sure you added that setting.