constructor()

in packages/static-website/src/static-website.ts [134:252]


  constructor(scope: Construct, id: string, props: StaticWebsiteProps) {
    super(scope, id);

    addMetric(scope, "static-website");

    this.node.setContext(
      "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy",
      true
    );

    this.validateProps(props);

    const accessLogsBucket = new Bucket(this, "AccessLogsBucket", {
      versioned: false,
      enforceSSL: true,
      autoDeleteObjects: true,
      removalPolicy: RemovalPolicy.DESTROY,
      encryption: BucketEncryption.S3_MANAGED,
      objectOwnership: ObjectOwnership.OBJECT_WRITER,
      publicReadAccess: false,
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
    });

    // S3 Bucket to hold website files
    this.websiteBucket =
      props.websiteBucket ??
      new Bucket(this, "WebsiteBucket", {
        versioned: true,
        enforceSSL: true,
        autoDeleteObjects: true,
        removalPolicy: RemovalPolicy.DESTROY,
        encryption:
          props.defaultWebsiteBucketEncryption ?? BucketEncryption.S3_MANAGED,
        objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
        encryptionKey: props.defaultWebsiteBucketEncryptionKey,
        publicReadAccess: false,
        blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
        serverAccessLogsPrefix: "website-access-logs",
        serverAccessLogsBucket: accessLogsBucket,
      });

    // Web ACL
    const { distributionProps } = props;
    const webAclArn =
      distributionProps?.webAclId ??
      (props.webAclProps?.disable
        ? undefined
        : new CloudfrontWebAcl(this, "WebsiteAcl", props.webAclProps)
            .webAclArn);

    // Cloudfront Distribution
    const logBucket =
      props.distributionProps?.logBucket ||
      new Bucket(this, "DistributionLogBucket", {
        enforceSSL: true,
        autoDeleteObjects: true,
        removalPolicy: RemovalPolicy.DESTROY,
        encryption:
          props.defaultWebsiteBucketEncryption ?? BucketEncryption.S3_MANAGED,
        objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
        encryptionKey: props.defaultWebsiteBucketEncryptionKey,
        publicReadAccess: false,
        blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
        serverAccessLogsPrefix: "distribution-access-logs",
        serverAccessLogsBucket: accessLogsBucket,
      });

    const defaultRootObject =
      distributionProps?.defaultRootObject ?? "index.html";
    this.cloudFrontDistribution = new Distribution(
      this,
      "CloudfrontDistribution",
      {
        ...distributionProps,
        webAclId: webAclArn,
        enableLogging: true,
        logBucket: logBucket,
        defaultBehavior: {
          ...distributionProps?.defaultBehavior,
          origin: S3BucketOrigin.withOriginAccessControl(this.websiteBucket),
          viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        },
        defaultRootObject,
        errorResponses: distributionProps?.errorResponses ?? [
          {
            httpStatus: 404, // We need to redirect "key not found errors" to index.html for single page apps
            responseHttpStatus: 200,
            responsePagePath: `/${defaultRootObject}`,
          },
        ],
      }
    );

    // Deploy Website
    this.bucketDeployment = new BucketDeployment(this, "WebsiteDeployment", {
      ...props.bucketDeploymentProps,
      sources: [
        Source.asset(props.websiteContentPath),
        ...(props.runtimeOptions
          ? [
              Source.jsonData(
                props.runtimeOptions?.jsonFileName ||
                  DEFAULT_RUNTIME_CONFIG_FILENAME,
                lazilyRender(this, props.runtimeOptions.jsonPayload)
              ),
            ]
          : []),
      ],
      destinationBucket: this.websiteBucket,
      // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
      distribution: this.cloudFrontDistribution,
    });

    new CfnOutput(this, "DistributionDomainName", {
      value: this.cloudFrontDistribution.domainName,
    });

    this.suppressCDKNagViolations(props);
  }