Serverless FrameworkでAngularアプリをAWS S3にデプロイ
やりたいこと
- AWS S3にAngularアプリを静的WEBホスティングする。
- CloudFrontでHTTPS通信&高速化する。
- 開発環境やステージング環境など、複数の環境へのデプロイを簡単に切り替えたい。 
- 上記作業をServerless Frameworkを使って自動化する。 
- 独自ドメインは......設定出来るけど、今回は除外。 
 →別記事にしました。
前提
- AWSアカウントを持っている。
- デプロイに必要な権限を持ったAWS IAMユーザのアクセスキー・シークレットアクセスキーを持っている。
- Angularアプリを作成済。(Angularである必要性はないです)
システム構成
Serverless Frameworkをインストール
$ npm install serverless $ npm install serverless-single-page-app-plugin $ npm install serverless-cloudfront-invalidate
Serverless Frameworkのバージョン
この記事で使用しているServerless Frameworkのバージョンです。
serverless:2.52.0 serverless-cloudfront-invalidate:1.9.0 serverless-single-page-app-plugin:1.0.2
serverless.ymlを作成
下記内容の serverless.yml を作成してプロジェクトのルートディレクトリに配置します。
service: angular-test-app
frameworkVersion: '2'
plugins:
  - serverless-single-page-app-plugin
  - serverless-cloudfront-invalidate
provider:
  name: aws
  stage: ${env:STAGE}
  region: ap-northeast-1
  stackName: ${self:service}-${self:provider.stage}
  environment:
    stage: ${self:provider.stage}
custom:
  s3Bucket: ${self:service}-deploy-${self:provider.stage}
  # angular.jsonのoutputPathに注意(この記事ではdist直下にビルドファイルを出力する設定をしています)
  s3LocalPath: dist/
  cloudfrontInvalidate:
    - distributionIdKey: CDNDistributionId
      autoInvalidate: true
      items:
        - '/*'
resources:
  Resources:
    WebAppS3Bucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.s3Bucket}
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: index.html
    WebAppS3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: WebAppS3Bucket
        PolicyDocument:
          Statement:
            - Sid: PublicReadGetObject
              Effect: Allow
              Principal: "*"
              Action:
                - s3:GetObject
              Resource:
                Fn::Join: ["", ["arn:aws:s3:::", { "Ref": "WebAppS3Bucket" }, "/*"]]
    WebAppCloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Origins:
            - DomainName:
                Fn::Join: ["", [{ "Ref": "WebAppS3Bucket" }, ".s3-ap-northeast-1.amazonaws.com"]]
              Id: WebApp
              CustomOriginConfig:
                HTTPPort: 80
                HTTPSPort: 443
                OriginProtocolPolicy: https-only
          PriceClass: PriceClass_200
          Enabled: 'true'
          DefaultRootObject: index.html
          CustomErrorResponses:
            - ErrorCode: 404
              ResponseCode: 200
              ResponsePagePath: /index.html
            - ErrorCode: 403
              ResponseCode: 200
              ResponsePagePath: /index.html
          DefaultCacheBehavior:
            AllowedMethods:
              - DELETE
              - GET
              - HEAD
              - OPTIONS
              - PATCH
              - POST
              - PUT
            TargetOriginId: WebApp
            ForwardedValues:
              QueryString: 'false'
              Cookies:
                Forward: none
            ViewerProtocolPolicy: https-only
  Outputs:
    WebAppS3BucketOutput:
      Value:
        'Ref': WebAppS3Bucket
    CDNDistributionId:
      Description: CDN distribution id.
      Value:
        Ref: WebAppCloudFrontDistribution
ビルド&デプロイ
# 環境変数の設定 ## 任意のステージ名 $ export STAGE=dev ## デプロイ権限を持ったIAMユーザのアクセスキー&シークレットアクセスキー $ export AWS_ACCESS_KEY_ID=XXX $ export AWS_SECRET_ACCESS_KEY=XXX # ビルド $ npx ng build --prod # デプロイ $ npx sls deploy -v -s $STAGE $ npx sls syncToS3 -v -s $STAGE
デプロイしたページを確認
ブラウザで https://ドメイン名 を開くとデプロイしたページを開くことができます。
※初回デプロイ時は開けるようになるまで時間がかかります。
ドメイン名はAWSのコンソール画面からCloudFrontのページを開くと確認できます。
次回
今回スルーした独自ドメインの設定をします。
https://d-oshige.blogspot.com/2021/11/serverless--s3-angular-02.html