constructor()

in packages/infra/lib/website-construct.ts [28:150]


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

        const cloudFrontOia = new cloudfront.CfnCloudFrontOriginAccessIdentity(this, 'OIA', {
            cloudFrontOriginAccessIdentityConfig: {
                comment: 'OIA for website.',
            },
        });

        const originAccessIdentity = cloudfront.OriginAccessIdentity.fromOriginAccessIdentityName(
            this,
            'OriginAccessIdentity',
            cloudFrontOia.ref
        );

        const sourceBucket = new s3.Bucket(this, 'WebsiteBucket', {
            websiteIndexDocument: 'index.html',
            encryption: s3.BucketEncryption.S3_MANAGED,
            blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
            enforceSSL: true,
        });

        const cloudFrontLoggingBucket = new s3.Bucket(this, 'S3BucketForWebsiteLogging', {
            blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
            encryption: s3.BucketEncryption.S3_MANAGED,
        });

        const cloudFrontDistribution = new cloudfront.CloudFrontWebDistribution(this, 'WebsiteCloudFront', {
            priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
            defaultRootObject: 'index.html',
            viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
            loggingConfig: {
                bucket: cloudFrontLoggingBucket,
            },
            originConfigs: [
                {
                    s3OriginSource: {
                        s3BucketSource: sourceBucket,
                        originAccessIdentity,
                    },
                    behaviors: [{ isDefaultBehavior: true }],
                },
            ],
            errorConfigurations: [
                {
                    errorCode: 404,
                    responseCode: 200,
                    responsePagePath: `/index.html`,
                    errorCachingMinTtl: 0,
                },
            ],
        });

        /**S3 bucket storing the dynamically generated index files.*/
        const websiteIndexBucket = new s3.Bucket(this, 'WebsiteIndexBucket', {
            blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
            encryption: s3.BucketEncryption.S3_MANAGED,
            enforceSSL: true,
        });

        const buildWebsiteIndexFunction = new lambdaNodeJs.NodejsFunction(this, 'BuildWebsiteIndexFunction', {
            runtime: lambda.Runtime.NODEJS_14_X,
            handler: 'handler',
            entry: path.join(__dirname, '../../website-index-builder/src/index.ts'),
            timeout: Duration.minutes(1),
            reservedConcurrentExecutions: 1,
        });

        websiteIndexBucket.grantReadWrite(buildWebsiteIndexFunction);

        const buildWebsiteIndexCustomResourceProvider = new customResource.Provider(
            this,
            'BuildWebsiteIndexCustomResourceProvider',
            {
                onEventHandler: buildWebsiteIndexFunction,
                logRetention: logs.RetentionDays.ONE_DAY,
            }
        );

        const indexFile = fs.readFileSync(path.join(props.websiteDistPath, 'index.html'), 'utf8');

        const buildWebsiteIndexCustomResource = new CustomResource(this, 'BuildWebsiteIndexCustomResource', {
            serviceToken: buildWebsiteIndexCustomResourceProvider.serviceToken,
            properties: {
                s3BucketName: websiteIndexBucket.bucketName,
                template: indexFile,
                apiUrl: props.api.url,
            },
        });

        buildWebsiteIndexCustomResource.node.addDependency(websiteIndexBucket, props.api);

        const cachedDeployment = new s3Deployment.BucketDeployment(this, 'CachedDeployWebsite', {
            sources: [
                s3Deployment.Source.asset(props.websiteDistPath, {
                    exclude: ['index.html', 'config.js', 'config.*.js'],
                }),
            ],
            prune: false,
            destinationBucket: sourceBucket,
            distribution: cloudFrontDistribution,
        });

        const uncachedDeployment = new s3Deployment.BucketDeployment(this, 'UncachedDeployWebsite', {
            sources: [s3Deployment.Source.bucket(websiteIndexBucket, buildWebsiteIndexCustomResource.ref)],
            destinationBucket: sourceBucket,
            prune: false,
            distribution: cloudFrontDistribution,
            cacheControl: [s3Deployment.CacheControl.noCache()],
        });

        uncachedDeployment.node.addDependency(cachedDeployment, buildWebsiteIndexCustomResource);

        new CfnOutput(this, 'WebsiteCloudfrontDistributionId', {
            value: cloudFrontDistribution.distributionId,
            exportName: `WebsiteCloudfrontDistributionId`,
        });

        new CfnOutput(this, 'CloudfrontDistributionDomainName', {
            value: cloudFrontDistribution.distributionDomainName,
            exportName: `WebsiteCloudfrontDistributionDomainName`,
        });
    }