タイプスクリプトAWS CDKを使用しているAWS S 3 + Cloudfront + Router 53への静的ウェブサイトの配備


今日のポストでは、我々は、グローバルCDNとしてCloudfrontセットアップを持っているS 3バケットに静的なウェブサイトのステップバイステップの展開を歩くつもりです.
ポストは、AWSタイプスクリプトCDKを使用して書かれます.

This example is used as a deployment for a static export of a NextJS 10 website. Find the blog post on how to do that here. That being said, this post is aimed at pushing any HTML to S3 to use a static website. I simply use the NextJS content to demo the final product and changes in steps required to get it done.


始める


新しいNPMプロジェクトを設定し、前提条件をインストールする必要があります.また、私たちはstacks ディレクトリは、我々のS 3スタックを格納し、いくつかのカスタムを取るために更新します.
# Create a root directory
mkdir infra
cd infra
# init npm project with default values
npm init -y
# Install required libraries
npm i @aws-cdk/aws-cloudfront @aws-cdk/aws-route53 @aws-cdk/aws-s3 @aws-cdk/aws-s3-deployment @aws-cdk/aws-certificatemanager @aws-cdk/core @aws-cdk/aws-route53-targets
# Dev installation reqs
npm i --save-dev typescript @types/node
# Make a stacks directory to house stacks
mkdir -p stacks stacks/s3-static-site-with-cloudfront
# Create main infra entry file
touch index.ts
# Create stack file
touch stacks/s3-static-site-with-cloudfront/index.ts
touch tsconfig.json cdk.json cdk.context.json

CDKの更新JSON


以下を加えますcdk.json ファイル
{
  "app": "node index"
}

コンテキストの設定


以下を加えますcdk.json ファイル
{
  "account": "<your-account-number>",
  "region": "us-east-1"
}
あなたのアカウントIDを得るためのガイドはAWS website , しかし、あなたがAWS CLIに精通しているならば、あなたは以下を使うことができます.
aws sts get-caller-identity
設定するaccount を返します.
コンテキストの詳細についてはAWS docs .

タイプスクリプト設定ファイルの更新


インtsconfig.json , 次を追加します.
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "commonjs",
    "lib": ["es2016", "es2017.object", "es2017.string"],
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": false,
    "inlineSourceMap": true,
    "inlineSources": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    // only required if using Node fns (which I do later on)
    "types": ["node"]
  }
}
これは、タイプスクリプトの設定をJavaScriptにコンパイルするためのCDKの基本的なタイプスクリプトです.

静的サイトスタックの処理


開くstacks/s3-static-site-with-cloudfront/index.ts 次の行を追加します.
import cloudfront = require("@aws-cdk/aws-cloudfront")
import route53 = require("@aws-cdk/aws-route53")
import s3 = require("@aws-cdk/aws-s3")
import s3deploy = require("@aws-cdk/aws-s3-deployment")
import acm = require("@aws-cdk/aws-certificatemanager")
import cdk = require("@aws-cdk/core")
import targets = require("@aws-cdk/aws-route53-targets/lib")
import { Stack, App, StackProps } from "@aws-cdk/core"
import path = require("path")

export interface StaticSiteProps extends StackProps {
  domainName: string
  siteSubDomain: string
}

/**
 * Static site infrastructure, which deploys site content to an S3 bucket.
 *
 * The site redirects from HTTP to HTTPS, using a CloudFront distribution,
 * Route53 alias record, and ACM certificate.
 */
export class StaticSiteStack extends Stack {
  constructor(parent: App, name: string, props: StaticSiteProps) {
    super(parent, name, props)

    const zone = route53.HostedZone.fromLookup(this, "Zone", {
      domainName: props.domainName,
    })
    const siteDomain = props.siteSubDomain + "." + props.domainName
    new cdk.CfnOutput(this, "Site", { value: "https://" + siteDomain })

    // Content bucket
    const siteBucket = new s3.Bucket(this, "SiteBucket", {
      bucketName: siteDomain,
      websiteIndexDocument: "index.html",
      websiteErrorDocument: "error.html",
      publicReadAccess: true,

      // The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete
      // the new bucket, and it will remain in your account until manually deleted. By setting the policy to
      // DESTROY, cdk destroy will attempt to delete the bucket, but will error if the bucket is not empty.
      removalPolicy: cdk.RemovalPolicy.DESTROY, // NOT recommended for production code
    })
    new cdk.CfnOutput(this, "Bucket", { value: siteBucket.bucketName })

    // TLS certificate
    const certificateArn = new acm.DnsValidatedCertificate(
      this,
      "SiteCertificate",
      {
        domainName: siteDomain,
        hostedZone: zone,
        region: "us-east-1", // Cloudfront only checks this region for certificates.
      }
    ).certificateArn
    new cdk.CfnOutput(this, "Certificate", { value: certificateArn })

    // CloudFront distribution that provides HTTPS
    const distribution = new cloudfront.CloudFrontWebDistribution(
      this,
      "SiteDistribution",
      {
        aliasConfiguration: {
          acmCertRef: certificateArn,
          names: [siteDomain],
          sslMethod: cloudfront.SSLMethod.SNI,
          securityPolicy: cloudfront.SecurityPolicyProtocol.TLS_V1_1_2016,
        },
        originConfigs: [
          {
            customOriginSource: {
              domainName: siteBucket.bucketWebsiteDomainName,
              originProtocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
            },
            behaviors: [{ isDefaultBehavior: true }],
          },
        ],
      }
    )
    new cdk.CfnOutput(this, "DistributionId", {
      value: distribution.distributionId,
    })

    // Route53 alias record for the CloudFront distribution
    new route53.ARecord(this, "SiteAliasRecord", {
      recordName: siteDomain,
      target: route53.RecordTarget.fromAlias(
        new targets.CloudFrontTarget(distribution)
      ),
      zone,
    })

    // Deploy site contents to S3 bucket
    new s3deploy.BucketDeployment(this, "DeployWithInvalidation", {
      sources: [s3deploy.Source.asset("./site-contents")],
      destinationBucket: siteBucket,
      distribution,
      distributionPaths: ["/*"],
    })
  }
}
上記から調整しましたAWS CDK Example あるものを、コンストラクタに対してスタックとして実行するように変換します.
ここで起こっていることを説明する
  • 引数のオブジェクトを渡すことができるインターフェイスstaticsitePropsがありますdomainName and siteSubDomain これは、例をデモすることができます.私が押すならばdomainName として.コムアンドsiteSubDomain S 3のCDK展開例として、あなたはウェブサイトがS 3 CDK展開例で利用できることを期待するでしょう.デンソーイソフェンCOM .これは変数siteDomain クラスの中で.
  • ARN証明書certificateArn を使用して使用できるようにしますhttps .
  • 新しいCloudFrontディストリビューションが作成され、distribution . The certificateArn は、ACM証明書リファレンスを設定するために使用され、siteDomain ここでは名前として使用されます.
  • 新しいaliasレコードが作成されますsiteDomain 値とターゲットを新しいCloudFrontディストリビューションに設定します.
  • 最後に、ソースから資産を展開する./site-contents これはスタックフォルダに対してそのフォルダにコードソースがあることを期待しています.我々の場合では、これは我々が望むものでありません、そして、その価値は変わります.展開もCDNのオブジェクトを無効にします.これはキャッシュの無駄なメカニズムがどのように動作するかによって、あなたが望むものであるかもしれません.あなたが資産をハッシュしたならばno-cache or max-age=0 あなたのためにindex.html ファイルを設定すると、このスイッチを切ることができます.無効は費用を要する.
  • 私の場合、上記のコードをインポートするために調整しますpath そして、s3deploy.Source.asset('./site-contents')s3deploy.Source.asset(path.resolve(__dirname, '../../../next-10-static-export/out')) (スタティックなHTMLビルド資産を持つ出力ディレクトリを指します).これは私の対応するブログ記事に関するものですexporting NextJS 10 static websites 直接.追加する必要があることに注意してくださいimport path = require('path') 上部にインストールする@types/node .

    静的スタックの使用


    のディレクトリに戻るindex.ts , スタックをインポートして使いましょう.
    import cdk = require("@aws-cdk/core")
    import { StaticSiteStack } from "./stacks/s3-static-site-with-cloudfront"
    
    const app = new cdk.App()
    const staticSite = new StaticSiteStack(app, "NextJS10StaticSite", {
      env: {
        account: app.node.tryGetContext("account"),
        region: app.node.tryGetContext("region"),
      },
      domainName: "dennisokeeffe.com",
      siteSubDomain: "nextjs-10-static-example",
    })
    
    // example of adding a tag - please refer to AWS best practices for ideal usage
    cdk.Tags.of(staticSite).add("Project", "NextJS 10 Example Deployment")
    
    app.synth()
    
    上記では、我々は単にスタックをインポート、新しいアプリケーションを作成するcdk APIは、その後のアプリケーションの新しいインスタンスに渡すStaticSite .
    あなたが思い出すならばStaticSite 読み取りconstructor(parent: Construct, name: string, props: StaticSiteProps) それで、3つの引数を期待します.
  • CDKアプリ.
  • スタックの“name”または識別子.
  • 我々のものに付着する小道具StaticSiteProps , したがって、我々のケースではdomainName and siteSubDomain .
  • パッケージの更新。JSON


    展開前に調整しましょうpackage.json 展開を支援するスクリプトもあります.
    {
      // rest omitted for brevity
      "scripts": {
        "build": "tsc",
        "watch": "tsc -w",
        "cdk": "cdk",
        "deploy": "cdk deploy",
        "destroy": "cdk destroy",
        "synth": "cdk synth"
      }
    }
    
    今、我々はロールする準備が整いました.

    サイトの配備


    Note: you must have your static folder from another project ready for this to work. Please refer to my post on a static site export of NextJS 10 if you would like to follow what I am doing here.


    私たちのサイトを展開するために、私たちはJavaScriptにタイプスクリプトを移して、それからCDKシンセサイザーを実行して、コマンドを配備する必要があります.

    Note: you'll need to make sure that your AWS credentials are configured for this to work. I personally use aws-vault.


    # Transpile TypeScript
    npm run build
    # Synth
    npm run synth
    # Deploy
    npm run deploy
    
    展開が開始される前に生成される新しいリソーステンプレートを受け入れる必要があります.
    私の特定のケースでは、私は私のポストから与えられたExporting Static NextJS 10 Websites
    最終的なライブ展開を見ることができますhttps://nextjs-10-static-example.dennisokeeffe.com .

    S 3のNEXTJS 10静的輸出

    資源

  • AWS CDK Static Site Example - GitHub
  • Exporting Static NextJS 10 Websites
  • AWS Vault - GitHub
  • AWS Runtime Context
  • Getting Your Account ID
  • Final, live website deployment
  • Final code
  • イメージ信用:Ignat Kushanrev
    もともと私の投稿blog . より隠された宝石のTwitter上で私に従ってください.