Serverless FrameworkでブラウザからCRUDできるアプリを作成する

前回作成したターミナルからCRUDできるアプリを改良して、もう少し実用的に、ブラウザからCRUDできるアプリを作成したいと思います。
前回作成したものはこちら=>Serverless FrameworkでCRUDを試す

この記事でやらないこと

aws cliのインストール
node.jsのインストール
Serverless Frameworkのインストール

ちなみにnodeをMacにインストールするときはbrewからanyenv経由でnodenvを入れるのがおすすめです。

前回からの変更点

前回からの変更点を書いていきます。(全て説明するとスーパー長くなるので)
最後にGitHubのリポジトリを載せておきます。

変更点としては以下です。

  • serverless.ymlが長くなったので、分けられるところは分けた
  • S3でホスティングできるようにした。
  • デプロイ時にS3にHTMLがアップロードされるようにした。

ファイルを分ける

serverless.ymlが長くなってきたので、それぞれのリソースごとにファイルをわけました。 cofigディレクトリを新たに作成して、IAM, DynamoDB, S3をわけました。

config/iam.yml

  - Effect: Allow
    Action:
      - dynamodb:DescribeTable
      - dynamodb:Query
      - dynamodb:Scan
      - dynamodb:GetItem
      - dynamodb:PutItem
      - dynamodb:UpdateItem
      - dynamodb:DeleteItem
    Resource: "arn:aws:dynamodb:ap-northeast-1:*:*"

config/dynamodb.yml

  Resources:
    TodosDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          -
            AttributeName: id
            AttributeType: S
        KeySchema:
          -
            AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: 'todos' 

config/s3.yml

Resources:
    StaticSite:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.webSiteName}
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html
    StaticSiteS3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: StaticSite
        PolicyDocument:
          Statement:
            - Sid: PublicReadGetObject
              Effect: Allow
              Principal: "*"
              Action:
              - s3:GetObject
              Resource:
                Fn::Join: ["", ["arn:aws:s3:::",{"Ref": "StaticSite"},"/*"]]
              Condition:
                IpAddress:
                  aws:SourceIp: "IP制限をするIPアドレス"

ファイルを作成したら、${file(./config/iam.yml)}のように書くことでファイルを読み出すことができます。
その際にsls printを実行すると、deploy時に実行されるymlを表示することができます。

service: serverless-crud

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-1
  stage: dev
  iamRoleStatements: ${file(./config/iam.yml)}
~~略~~

resources:
  - ${file(./config/s3.yml)}
  - ${file(./config/dynamodb.yml)}
~~略~~

S3ホスティング

上記のs3.ymlですでにS3ホスティングする設定を書いています。
${self:custom.webSiteName}serverless.ymlの最後で記述します。S3のバケット名だと思って大丈夫です。

デプロイ時にS3にファイルをアップロード

sls deployする時にホスティングするS3にHTML・CSS(今回はBootstrap利用のためなし), JavaScriptのファイルをアップロードできるようにします。
Serverless Frameworkの公式機能にはないので、npmのプラグインを利用します

Serverless S3 Sync

$ npm install --save serverless-s3-sync

そしたらserverless.ymlの最後に下記を追記します

plugins:
  - serverless-s3-sync

custom:
  webSiteName: 利用したいS3のバケット名
  s3Sync:
    - bucketName: ${self:custom.webSiteName}
      localDir: static

${self:custom.webSiteName}に利用したいS3バケット名が代入されます。ここには( )" "などは不要なので注意してください

あとはstaticディレクトリを作成してその中にindex.html, error.htmlなどのファイルを入れれば完了です!

デプロイしましょう!!

sls deploy

AddしたりUpdateしたりすると以下のようになるはずです。
UpdateやDeleteがID指定で行っているので、直前に追加した項目でUpdateやDeleteを行うろエラーになる仕様です。
IDをハッシュ値などではなくタイムスタンプなどにしてフロント側で設定できるようにjsとLambdaを書き換えると良いかもしれません

GitHubのリポジトリはこちら => https://github.com/t-sakurai816/serverless_crud