import { Construct } from "constructs"; import * as s3 from "aws-cdk-lib/aws-s3"; import * as acm from "aws-cdk-lib/aws-certificatemanager"; import * as route53 from "aws-cdk-lib/aws-route53"; import * as cloudfront from "aws-cdk-lib/aws-cloudfront"; import { BaseSiteDomainProps, BaseSiteReplaceProps, BaseSiteCdkDistributionProps } from "./BaseSite.js"; import { SSTConstruct } from "./Construct.js"; import { FunctionBindingProps } from "./util/functionBinding.js"; export interface StaticSiteFileOptions { exclude: string | string[]; include: string | string[]; cacheControl: string; } export interface StaticSiteProps { /** * Path to the directory where the website source is located. * * @example * ```js * new StaticSite(stack, "Site", { * path: "path/to/src", * }); * ``` */ path: string; /** * The name of the index page (e.g. "index.html") of the website. * @default index.html * @example * ```js * new StaticSite(stack, "Site", { * indexPage: "other-index.html", * }); * ``` */ indexPage?: string; /** * The error page behavior for this website. Takes either an HTML page (ie. `"404.html"`) or the `"redirect_to_index_page"` to redirect to the 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. * @default redirect_to_index_page * @example * ```js * new StaticSite(stack, "Site", { * errorPage: "redirect_to_index_page", * }); * ``` */ errorPage?: "redirect_to_index_page" | Omit; /** * The command for building the website * @default no build command * @example * ```js * new StaticSite(stack, "Site", { * buildCommand: "npm run build", * }); * ``` */ buildCommand?: string; /** * 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`](#path) where the website source is located. * @default entire "path" directory * @example * ```js * new StaticSite(stack, "Site", { * buildOutput: "build", * }); * ``` */ buildOutput?: string; /** * 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. * * Defaults to no cache control for HTML files, and a 1 year cache control for JS/CSS files. * ```js * [ * { * exclude: "*", * include: "*.html", * cacheControl: "max-age=0,no-cache,no-store,must-revalidate", * }, * { * exclude: "*", * include: ["*.js", "*.css"], * cacheControl: "max-age=31536000,public,immutable", * }, * ] * ``` * @example * ```js * new StaticSite(stack, "Site", { * buildOutput: "dist", * fileOptions: [{ * exclude: "*", * include: "*.js", * cacheControl: "max-age=31536000,public,immutable", * }] * }); * ``` */ fileOptions?: StaticSiteFileOptions[]; /** * Pass in a list of placeholder values to be replaced in the website content. For example, the follow configuration: * * @example * ```js * new StaticSite(stack, "frontend", { * replaceValues: [ * { * files: "*.js", * search: "{{ API_URL }}", * replace: api.url, * }, * { * files: "*.js", * search: "{{ COGNITO_USER_POOL_CLIENT_ID }}", * replace: auth.cognitoUserPoolClient.userPoolClientId, * }, * ], * }); * ``` */ replaceValues?: StaticSiteReplaceProps[]; /** * The customDomain for this website. SST supports domains that are hosted either on [Route 53](https://aws.amazon.com/route53/) or externally. * * Note that you can also migrate externally hosted domains to Route 53 by [following this guide](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/MigratingDNS.html). * * @example * ```js * new StaticSite(stack, "Site", { * path: "path/to/src", * customDomain: "domain.com", * }); * ``` * * @example * ```js * new StaticSite(stack, "Site", { * path: "path/to/src", * customDomain: { * domainName: "domain.com", * domainAlias: "www.domain.com", * hostedZone: "domain.com" * } * }); * ``` */ customDomain?: string | StaticSiteDomainProps; /** * An object with the key being the environment variable name. Note, this requires your build tool to support build time environment variables. * * @example * ```js * new StaticSite(stack, "frontend", { * environment: { * REACT_APP_API_URL: api.url, * REACT_APP_USER_POOL_CLIENT: auth.cognitoUserPoolClient.userPoolClientId, * }, * }); * ``` */ environment?: Record; /** * While deploying, SST removes old files that no longer exist. Pass in `false` to keep the old files around. * * @default true * * @example * ```js * new StaticSite(stack, "frontend", { * purgeFiles: false * }); * ``` */ purgeFiles?: boolean; /** * When running `sst start`, a placeholder site is deployed. This is to ensure that the site content remains unchanged, and subsequent `sst start` can start up quickly. * * @default false * * @example * ```js * new StaticSite(stack, "frontend", { * disablePlaceholder: true * }); * ``` */ disablePlaceholder?: boolean; vite?: { /** * The path where code-gen should place the type definition for environment variables * @default "src/sst-env.d.ts" * @example * ```js * new StaticSite(stack, "frontend", { * vite: { * types: "./other/path/sst-env.d.ts", * } * }); * ``` */ types?: string; }; /** * While deploying, SST waits for the CloudFront cache invalidation process to finish. This ensures that the new content will be served once the deploy command finishes. However, this process can sometimes take more than 5 mins. For non-prod environments it might make sense to pass in `false`. That'll skip waiting for the cache to invalidate and speed up the deploy process. * * @default true * * @example * ```js * new StaticSite(stack, "frontend", { * waitForInvalidation: false * }); * ``` */ waitForInvalidation?: boolean; cdk?: { /** * Allows you to override default id for this construct. */ id?: string; /** * Allows you to override default settings this construct uses internally to ceate the bucket * * @example * ```js * new StaticSite(stack, "Site", { * path: "path/to/src", * cdk: { * bucket: { * bucketName: "mybucket", * }, * } * }); * ``` */ bucket?: s3.BucketProps | s3.IBucket; /** * Configure the internally created CDK `Distribution` instance. * * @example * ```js * new StaticSite(stack, "Site", { * path: "path/to/src", * cdk: { * distribution: { * comment: "Distribution for my React website", * }, * } * }); * ``` */ distribution?: StaticSiteCdkDistributionProps; }; } export interface StaticSiteDomainProps extends BaseSiteDomainProps { } export interface StaticSiteReplaceProps extends BaseSiteReplaceProps { } export interface StaticSiteCdkDistributionProps extends BaseSiteCdkDistributionProps { } /** * The `StaticSite` construct is a higher level CDK construct that makes it easy to create a static website. * * @example * * Deploys a plain HTML website in the `path/to/src` directory. * * ```js * import { StaticSite } from "@serverless-stack/resources"; * * new StaticSite(stack, "Site", { * path: "path/to/src", * }); * ``` */ export declare class StaticSite extends Construct implements SSTConstruct { readonly id: string; readonly cdk: { /** * The internally created CDK `Bucket` instance. */ bucket: s3.Bucket; /** * The internally created CDK `Distribution` instance. */ distribution: cloudfront.Distribution; /** * The Route 53 hosted zone for the custom domain. */ hostedZone?: route53.IHostedZone; certificate?: acm.ICertificate; }; private props; private isPlaceholder; private assets; private filenamesAsset?; private awsCliLayer; constructor(scope: Construct, id: string, props: StaticSiteProps); /** * The CloudFront URL of the website. */ get url(): string; /** * If the custom domain is enabled, this is the URL of the website with the custom domain. */ get customDomainUrl(): string | undefined; /** * The ARN of the internally created S3 Bucket. */ get bucketArn(): string; /** * The name of the internally created S3 Bucket. */ get bucketName(): string; /** * The ID of the internally created CloudFront Distribution. */ get distributionId(): string; /** * The domain name of the internally created CloudFront Distribution. */ get distributionDomain(): string; getConstructMetadata(): { type: "StaticSite"; data: { distributionId: string; customDomainUrl: string | undefined; }; }; /** @internal */ getFunctionBinding(): FunctionBindingProps; private generateViteTypes; private buildApp; private bundleAssets; private bundleFilenamesAsset; private createS3Bucket; private createS3Deployment; private createCfDistribution; private createCloudFrontInvalidation; protected validateCustomDomainSettings(): void; protected lookupHostedZone(): route53.IHostedZone | undefined; private createCertificate; protected createRoute53Records(): void; private getS3ContentReplaceValues; private registerSiteEnvironment; }