StaticSite

The StaticSite construct is a higher level CDK construct that makes it easy to create a static website. It provides a simple way to build and deploy the site to an S3 bucket; setup a CloudFront CDN for fast content delivery; and configure a custom domain for the website URL. In addition:

  • Visitors to the http:// url will be redirected to the https:// URL.
  • If a domain alias is configured, visitors to the alias domain will be redirected to the main one. So if www.example.com is the domain alias for example.com, visitors to www.example.com will be redirected to example.com.

See the examples for more details.

Initializer#

new StaticSite(scope: Construct, id: string, props: StaticSiteProps)

Parameters

Examples#

The StaticSite construct is designed to make it easy to get started with, while allowing for a way to fully configure it as well. Let's look at how, through a couple of examples.

Creating a plain HTML site#

Deploys a plain HTML website in the path/to/src directory.

import { StaticSite } from "@serverless-stack/resources";
new StaticSite(this, "Site", {
path: "path/to/src",
});

Creating a React site#

import { StaticSiteErrorOptions } from "@serverless-stack/resources";
new StaticSite(this, "ReactSite", {
path: "path/to/src",
buildOutput: "build",
buildCommand: "npm run build",
errorPage: StaticSiteErrorOptions.REDIRECT_TO_INDEX_PAGE,
});

Creating a Vue.js site#

new StaticSite(this, "VueJSSite", {
path: "path/to/src",
buildOutput: "dist",
buildCommand: "npm run build",
errorPage: StaticSiteErrorOptions.REDIRECT_TO_INDEX_PAGE,
});

Creating a Gatsby site#

new StaticSite(this, "GatsbySite", {
path: "path/to/src",
errorPage: "404.html",
buildOutput: "public",
buildCommand: "npm run build",
});

Creating a Jekyll site#

new StaticSite(this, "JekyllSite", {
path: "path/to/src",
errorPage: "404.html",
buildOutput: "_site",
buildCommand: "bundle exec jekyll build",
});

Creating an Angular site#

new StaticSite(this, "AngularSite", {
path: "path/to/src",
buildOutput: "dist",
buildCommand: "ng build --output-path dist",
errorPage: StaticSiteErrorOptions.REDIRECT_TO_INDEX_PAGE,
});

Configuring custom domains#

You can also configure the website with a custom domain. SST currently supports domains that are configured using Route 53. If your domains are hosted elsewhere, you can follow this guide to migrate them to Route 53.

Using the basic config#

new StaticSite(this, "Site", {
path: "path/to/src",
customDomain: "domain.com",
});

Redirect www to non-www#

new StaticSite(this, "Site", {
path: "path/to/src",
customDomain: {
domainName: "domain.com",
domainAlias: "www.domain.com",
},
});

Configuring domains across stages#

export default class MyStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
new StaticSite(this, "Site", {
path: "path/to/src",
customDomain: {
domainName: scope.stage === "prod" ? "domain.com" : `${scope.stage}.domain.com`,
domainAlias: scope.stage === "prod" ? "www.domain.com" : undefined,
},
});
}
}

Using the full config#

new StaticSite(this, "Site", {
path: "path/to/src",
customDomain: {
domainName: "domain.com",
domainAlias: "www.domain.com",
hostedZone: "domain.com",
},
});

Importing an existing certificate#

import { Certificate } from "@aws-cdk/aws-certificatemanager";
new StaticSite(this, "Site", {
path: "path/to/src",
customDomain: {
domainName: "domain.com",
certificate: Certificate.fromCertificateArn(this, "MyCert", certArn),
},
});

Note that, the certificate needs be created in the us-east-1(N. Virginia) region as required by AWS CloudFront.

Specifying a hosted zone#

If you have multiple hosted zones for a given domain, you can choose the one you want to use to configure the domain.

import { HostedZone } from "@aws-cdk/aws-route53";
new StaticSite(this, "Site", {
path: "path/to/src",
customDomain: {
domainName: "domain.com",
hostedZone: HostedZone.fromHostedZoneAttributes(this, "MyZone", {
hostedZoneId,
zoneName,
}),
},
});

Configure caching#

Configure the Cache Control settings based on differnt file types.

new StaticSite(this, "Site", {
path: "path/to/src",
buildOutput: "build",
buildCommand: "npm run build",
errorPage: StaticSiteErrorOptions.REDIRECT_TO_INDEX_PAGE,
fileOptions: [
{
exclude: "*",
include: "*.html",
cacheControl: "max-age=0,no-cache,no-store,must-revalidate",
},
{
exclude: "*",
include: ["*.js", "*.css"],
cacheControl: "max-age=31536000,public,immutable",
},
],
});

This configures all the .html files to not be cached by the, while the .js and .css files to be cached forever.

Note that, you need to specify the exclude: "*" along with the include option. It allows you to pick the files you want, while excluding everything else.

Replace deployed values#

Replace placeholder values in your website content with the deployed values. So you don't have to hard code the config from your backend.

new StaticSite(this, "ReactSite", {
path: "path/to/src",
buildOutput: "build",
buildCommand: "npm run build",
errorPage: StaticSiteErrorOptions.REDIRECT_TO_INDEX_PAGE,
replaceValues: [
{
files: "**/*.js",
search: "{{ API_URL }}",
replace: api.url,
},
{
files: "**/*.js",
search: "{{ COGNITO_USER_POOL_CLIENT_ID }}",
replace: auth.cognitoUserPoolClient.userPoolClientId,
},
],
});

This replaces {{ API_URL }} and {{ COGNITO_USER_POOL_CLIENT_ID }} with the deployed API endpoint and Cognito User Pool Client Id in all the .js files in your React app.

Configuring the S3 Bucket#

Configure the internally created CDK Bucket instance.

import { RemovalPolicy } from "@aws-cdk/core";
new StaticSite(this, "Site", {
path: "path/to/src",
s3Bucket: {
removalPolicy: RemovalPolicy.DESTROY,
},
});

Configuring the CloudFront Distribution#

Configure the internally created CDK Distribution instance.

new StaticSite(this, "Site", {
path: "path/to/src",
cfDistribution: {
comment: "Distribution for my React website",
},
});

Configuring the CloudFront default behavior#

The default behavior of the CloudFront distribution uses the internally created S3 bucket as the origin. You can configure this behavior.

import { ViewerProtocolPolicy, AllowedMethods } from "@aws-cdk/aws-cloudfront";
new StaticSite(this, "Site", {
path: "path/to/src",
cfDistribution: {
defaultBehavior: {
viewerProtocolPolicy: ViewerProtocolPolicy.HTTPS_ONLY,
allowedMethods: AllowedMethods.ALLOW_ALL,
},
},
});

Using Lambda@Edge#

import { LambdaEdgeEventType, experimental } from "@aws-cdk/aws-cloudfront";
const edgeFunc = new experimental.EdgeFunction(this, "MyFunction", {
runtime: lambda.Runtime.NODEJS_12_X,
handler: "lambda.handler",
code: lambda.Code.fromAsset("path/to/dir"),
stackId: `${scope.logicalPrefixedName("edge-lambda")}`,
});
new StaticSite(this, "Site", {
path: "path/to/src",
cfDistribution: {
defaultBehavior: {
edgeLambdas: [
{
functionVersion: edgeFunc.currentVersion,
eventType: LambdaEdgeEventType.VIEWER_RESPONSE,
},
],
},
},
});

Note that, Lambda@Edge functions will be created in the us-east-1 region, regardless of the region of your SST app. If the app is in us-east-1, the Lambda function is created directly in the stack. If the app is not in us-east-1, the Lambda function will be created in a new stack with the provided stackId. And the new stack will be deployed to us-east-1.

caution

On sst remove, the Lambda@Edge functions cannot be removed right away. CloudFront needs to remove the function replicas from the edge locations. This can take up to a few hours. If the stack fails to remove, simply wait for some time and retry.

Properties#

An instance of StaticSite contains the following properties.

url#

Type: string

The CloudFront URL of the website.

customDomainUrl?#

Type: string

If the custom domain is enabled, this is the URL of the website with the custom domain.

bucketArn#

Type: string

The ARN of the internally created CDK Bucket instance.

bucketName#

Type: string

The name of the internally created CDK Bucket instance.

distributionId#

Type: string

The ID of the internally created CDK Distribution instance.

distributionDomain#

Type: string

The domain name of the internally created CDK Distribution instance.

s3Bucket#

Type : cdk.aws-s3.Bucket

The internally created CDK Bucket instance.

cfDistribution#

Type : cdk.aws-cloudfront.Distribution

The internally created CDK Distribution instance.

StaticSiteProps#

path#

Type : string

Path to the directory where the website source is located.

indexPage?#

Type : string, defaults to index.html

The name of the index page (e.g. "index.html") of the website.

errorPage?#

Type : string | StaticSiteErrorOptions

The error page behavior for this website. Takes either an HTML page.

404.html

Or the StaticSiteErrorOptions to redirect to the index page.

StaticSiteErrorOptions.REDIRECT_TO_INDEX_PAGE

Note that, if the error pages are redirected to the index page, the HTTP status code is set to 200. This is necessary for single page apps, that handle 404 pages on the client side.

buildCommand?#

Type : string, defaults to no build command

The command for building the website (e.g. "npm run build").

buildOutput?#

Type : string, defaults to the path

The directory with the content that will be uploaded to the S3 bucket. If a buildCommand is provided, this is usually where the build output is generated. The path is relative to the path where the website source is located.

customDomain?#

Type : string | StaticSiteDomainProps

The customDomain for this website. SST currently supports domains that are configured using Route 53. If your domains are hosted elsewhere, you can follow this guide to migrate them to Route 53.

Takes either the domain as a string.

"domain.com"

Or the StaticSiteDomainProps.

{
domainName: "domain.com",
domainAlias: "www.domain.com",
hostedZone: "domain.com",
}

fileOptions?#

Type : StaticSiteDomainProps[]

Pass in a list of file options to configure cache control for different files. Behind the scenes, the StaticSite construct uses a combination of the s3 cp and s3 sync commands to upload the website content to the S3 bucket. An s3 cp command is run for each file option block, and the options are passed in as the command options.

For example, the follow configuration:

{
exclude: "*",
include: "*.js",
cacheControl: "max-age=31536000,public,immutable",
}

runs the s3 cp commands:

s3 cp CONTENT_DIR s3://BUCKET_NAME/deploy-2021-06-21T06:05:37.720Z --recursive --exclude * --include *.js --cache-control max-age=31536000,public,immutable

After the s3 cp commands are run, the construct will run an s3 sync command to upload all files not explicitely configured in fileOptions.

replaceValues?#

Type : StaticSiteReplaceProps[]

Pass in a list of placeholder values to be replaced in the website content. For example, the follow configuration:

{
files: "*.js",
search: "{{ API_URL }}",
replace: api.url,
}

Replaces {{ API_URL }} with the deployed API url in all the .js files.

s3Bucket?#

Type: cdk.aws-s3.BucketProps

Pass in a cdk.aws-s3.BucketProps value to override the default settings this construct uses to create the CDK Bucket internally.

cfDistribution?#

Type: StaticSiteCdkDistributionProps

Pass in a StaticSiteCdkDistributionProps value to override the default settings this construct uses to create the CDK Distribution internally.

StaticSiteDomainProps#

domainName#

Type : string

The domain to be assigned to the website URL (ie. domain.com).

Currently supports domains that are configured using Route 53.

domainAlias?#

Type : string, defaults to no alias configured

An alternative domain to be assigned to the website URL. Visitors to the alias will be redirected to the main domain. (ie. www.domain.com).

Use this to create a www. version of your domain and redirect visitors to the root domain.

hostedZone?#

Type : string | cdk.aws-route53.IHostedZone, defaults to the domain name

The hosted zone in Route 53 that contains the domain. Takes the name of the hosted zone as a string or the hosted zone construct cdk.aws-route53.HostedZone. By default, SST will look for a hosted zone matching the domainName that's passed in.

Set this option if SST cannot find the hosted zone in Route 53.

certificate?#

Type : cdk.aws-certificatemanager.ICertificate, defaults to undefined

The certificate for the domain. By default, SST will create a certificate with the domain name from the domainName option. The certificate will be created in the us-east-1(N. Virginia) region as required by AWS CloudFront.

Set this option if you have an existing certificate in the us-east-1 region in AWS Certificate Manager you want to use.

StaticSiteFileOption#

exclude#

Type : string | string[]

Exclude all files that matches the given pattern.

include#

Type : string | string[]

Don't exclude files that match the given pattern.

cacheControl#

Type : string

Specifies caching behavior for the included files.

StaticSiteReplaceProps#

files#

Type : string

The glob pattern of all files to be searched.

search#

Type : string

A string that is to be replaced by the replace prop. Note that this isn't a regular expression. And all the occurrences will be replaced.

replace#

Type : string

The string that replaces the substring specified by the specified search prop.

StaticSiteCdkDistributionProps#

StaticSiteCdkDistributionProps extends cdk.aws-cloudfront.DistributionProps with the exception that the defaultBehavior field is optional and takes a cdk.aws-cloudfront.AddBehaviorOptions object.

You can use StaticSiteCdkDistributionProps to configure the CloudFront distribution properties.

StaticSiteErrorOptions#

An enum with the following members representing the field types.

MemberDescription
REDIRECT_TO_INDEX_PAGERedirect any invalid url to the indexPage.