LambdaをCodePipelineでデプロイするときにdevDependenciesを外して軽くする


ハマったこと

  • Lambda@Edgeでそこそこ複雑な認証処理を書こうとした
  • なので真面目にmocha,power-assert,sinonを使ってユニットテスト
  • 当然、CodeBuildでビルドするときにもnpm testを実行
  • そのままデプロイ
  • Lambda@Edgeのサイズ制限(圧縮して1MB)に引っかかった

原因

mocha,power-assert,sinonのセットは結構サイズがでかい。node_modulesのサイズがエライことに。

方向性

CodeBuild内でのnpm testはやりたい。

とはいえ、デプロイするときはmocha,power-assert,sinon(≒devDependenciesの中身)は含めたくない。

テストした後、消してもう一回dependenciesだけインストールすればいいんじゃね?

やってみた

package.json

{
  "name": "oidc-inspection",
  "version": "0.0.1",
  "description": "OIDC Inspection",
  "main": "src/index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "tetsuya.zama",
  "license": "ISC",
  "devDependencies": {
    "mocha": "^5.2.0",
    "power-assert": "^1.6.1",
    "sinon": "^6.3.5"
  },
  "dependencies": {
    "cookie": "^0.3.1",
    "node-jose": "^1.0.0"
  }
}

template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Inspection about integration between CloudFront and Cognito
Resources:
  oidcInspection:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: src/index.handler
      Runtime: nodejs6.10
      Role: !GetAtt oidcInspectionRole.Arn
      Description: ''
      MemorySize: 128
      Timeout: 5
      AutoPublishAlias: live
  oidcInspectionRole:
      Type: "AWS::IAM::Role"
      Properties:
          Path: "/"
          ManagedPolicyArns:
              - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
          AssumeRolePolicyDocument:
            Version: "2012-10-17"
            Statement:
              -
                Sid: "AllowLambdaServiceToAssumeRole"
                Effect: "Allow"
                Action: 
                  - "sts:AssumeRole"
                Principal:
                  Service: 
                    - "lambda.amazonaws.com"
                    - "edgelambda.amazonaws.com"

buildspec.yml

version: 0.2 #versionが0.1だと各Commandが別のシェルで実行されてしまうので成立しないっぽい

phases:
    pre_build:
        commands:
            - npm install #テストの為に1回全部インストール
            - npm test #テスト実行
    build:
        commands:
            - rm -rf node_modules #テストが終わったので1回node_modulesを消す
            - rm -rf test #ついでにtestディレクトリも消しておく
            - npm install --production #--productionをつけるとdevDependenciesはインストールされない
            # あとは普通にpackageして、artifactsに渡せばOK
            - aws cloudformation package --template-file template.yaml --s3-bucket oidc-inspaction-sam-lambda --output-template-file outputSamTemplate.yaml

artifacts:
    files:
        - template.yaml
        - outputSamTemplate.yaml

結果

もともと圧縮して4MBだったものが0.8MBに削減。無事にLambda@Edgeとしてデプロイすることができた。

誰かもっとスマートな方法があったら教えてください。。。