echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【Serverless Framework】package設定について&パッケージが終わらない場合の対策

概要

以前、簡単デプロイとserverless.ymlの記載についてでServerless Framework(以下SFW)のserverless.ymlファイルについての記事を書きました。
今回はその中の「package」項目(=デプロイパッケージの設定)に関する内容です。

Serverless Framework公式サイト

共通設定

全functionsで共通のpackage設定は、ルートの「package」項目内に設定します。
主に、下記の設定項目があります。

項目名 意味 備考
exclude デプロイパッケージに含めないファイル/フォルダを指定する 基本的に、ここに含めなかったファイル/フォルダはすべてパッケージに含まれる
include excludeで指定したフォルダの中で、パッケージに含めたいファイル/フォルダを指定する
artifact デプロイファイルとして設定したい*.zipファイルを指定する 指定すると、SFWのパッケージ処理は無視される(設定も含め)?
※ここはイマイチよくわかってません。別ツールでデプロイパッケージを作成する場合に指定する?
individually functionsの関数について、個別にパッケージを行う(=*.zipファイルを作成する)かどうか(true/false) デフォルトはfalse
excludeDevDependencies パッケージに含める全フォルダ内のpackage.jsonの「devDependencies」に定義したモジュールを自動でパッケージから除外するかどうか(true/false) デフォルトはtrue。
詳細は「Excluding development dependenciesが終わらない場合」を参照

関数別設定(functions)

「共通設定」に記載した設定項目ですが、これはfunctionsの各関数で個別に設定することも可能です。(基本は両方を組み合わせて使用する...のかな?)

(例)

package:
  individually: true
  exclude:
    - lambda/**
    - src/**
  include:
    - lambda/common/mysql2  
  
functions:
 func1:
    handler: lambda/func1/index.handler
  package:
    individually: true
    include:
      - lambda/func1/*
    exclude:
      - lambda/func1/*.json  
  
 func2:
    handler: lambda/func2/index.handler
  package:
    individually: true
    include:
      - lambda/func2/*
    exclude:
      - lambda/func2/*.json

※上記の例だと、こんな感じでファイルができます。(デフォルトでは「.serverless」フォルダ内にできます)

  • func1.zip
    • lambda
      • common
        • mysql2
      • func1
        • index.js
  • func2.zip
    • lambda
      • common
        • mysql2
      • func2
        • index.js

勘違いしてたこと

共通設定だけではだめ

最初は「共通設定だけ設定すればいいんだな」と、共通部分の設定のみ行っていたのですが、これだと個別の*.zipファイルはできますが、

  • 各*.zipファイルに、全functionが格納されている

という、変な状態になります。

(例)下記serverless.ymlでパッケージを行うと...

package:
  individually: true
  exclude:
    - src/**
  include:
    - lambda/**  

本当は「 関数別設定(functions) 」記載した構成の個別*.zipファイルができてほしいのですが、実際はこうなります。(commonフォルダは省略)

  • func1.zip
    • lambda
      • func1
        • index.js
      • func2
        • index.js
  • func2.zip
    • lambda
      • func1
        • index.js
      • func2
        • index.js

...そりゃあ、パッケージ処理が遅くなりますよね。

functions格納フォルダは共通設定でexcludeする

また、始めは「(上記の例の場合)共通設定でlambdaフォルダは含めないとダメだろ」と、serverless.ymlに下記の設定をしていました。
※(全functionsの格納フォルダである、lambdaフォルダをパッケージに含めている)

package:
  individually: true
  exclude:
    - src/**
  
functions:
 func1:
    handler: lambda/func1/index.handler
  package:
    individually: true
    include:
      - lambda/func1/*
    exclude:
      - lambda/func1/*.json  
  
 func2:
    handler: lambda/func2/index.handler
  package:
    individually: true
    include:
      - lambda/func2/*
    exclude:
      - lambda/func2/*.json

が、これで作成される*.zipファイルは、先述の「共通設定だけではだめ」でできた構成と同じになります。

なので、「関数別設定(functions)」に記載したserverless.ymlファイルのように、

  • 全functions共通で必要なもの以外は、すべて共通設定でexcludeし、functionsで個別にincludeする

ということでしょうね。

Excluding development dependenciesが終わらない場合

AWS CLIの「serverless package」コマンドで実際にデプロイパッケージ作成処理を行った際、

  • 「Excluding development dependencies...」が全然終わらない

という現象が発生する場合があります。

これは、SFWがデプロイパッケージ作成の際、

  • (パッケージ対象フォルダの)全package.json内のdevDependenciesのモジュールを再帰的にチェックし、パッケージ対象から外す

処理を行っているからです。

一見よくわからないかもしれませんが、例えばどこかでpackage.jsonがあったら、

  • そのpackage.jspnのdevDependenciesをパッケージから外す
  • そのpackage.jsonの全dependenciesモジュールについて、一つずつ
    • そのモジュールのpackage.jsonを見に行く
    • そのモジュールのpackage.jsonのdevDependenciesをパッケージから外す
    • そのモジュールのpackage.jsonの全dependenciesモジュールについて、一つずつ...(以下繰り返し)

を全package.json、及びそのdependencies&devDependenciesについて行うので、設定次第ではめちゃくちゃ遅くなります。

で、対策ですが「共通設定」で説明した「excludeDevDependencies」を「false」に設定すればOKです。

※ただし、その場合devDependenciesのパッケージが除外されないので、パッケージサイズが大きくなるケースもあります。
わかるなら事前にexcludeするなどの対策が必要です。

package:
  individually: true
  exclude:
    - lambda/**
    - src/**
  include:
    - lambda/common/mysql2  
  excludeDevDependencies: false

参考:“Excluding Development Dependencies” Takes Forever

まとめ

今回は久々にSFWの内容になりました。
SFWは本当に便利&奥が深いので、時間が許す限り、もっともっと突き詰めてみたいところです。

ただ、公式サイトが最近リニューアルしましたが、その結果なんか記事が見にくく(探しにくく)なった感じがしますが...

てか、AWS Cognitoの記事はどうなった...