Lambdaのデプロイパッケージにnode_modulesを含む場合はレイヤーに分離すると便利

例えばNodeJSでAurora Serverlessに接続しようとしたときにはデプロイパッケージは次のようなディレクトリ構造となり、zipで圧縮してアップロードしなくてはならない。

index.js
node_modules/bignumber.js
node_modules/core-util-is
node_modules/inherits
node_modules/isarray
node_modules/mysql
node_modules/process-nextick-args
node_modules/readable-stream
node_modules/safe-buffer
node_modules/sqlstring
node_modules/string_decoder
node_modules/util-deprecate

まあzip圧縮とアップロードの効率化はコマンドラインからなんとかなるかもだ。
しかしライブラリの容量を含めてコードが3MBを越えるとAWSコンソール上のオンラインエディタから編集できなくなるという問題もあり、ちょこちょこと色々試すには不便である。

この解決策としてLambdaにはレイヤーという機能が昨年末に追加された。
レイヤーを作るとデプロイパッケージにnode_modulesを含める必要がなくなる。index.jsだけアップすれば良いので3MB制限にも引っかからずオンラインエディタでコードを編集できなくなることもない。ので色々と捗る。

レイヤーに登録するzipファイルの作成

レイヤーにはライブラリのパッケージをzipで固めたものを登録する。

$ mkdir -p layers/mysql/nodejs/node_modules
$ cd layers/mysql/nodejs
$ npm install mysql

ディレクトリ名のnodejsはAWS Lambdaレイヤーのお約束で決まっているものなのでそのようにする(Pythonを使った時はpythonになるしJavaを使っているときにはjavaになるしRubyならrubyになる)
node_modulesはライブラリのパッケージを入れる場所として。

npm installが終わったらnodejsディレクトリを圧縮してzipファイルを作成する。
Macであれば右クリックで圧縮。ファイル名はnodejs.zipのままでもいいしmysql.zipに直してもいい。

できあがったzipファイルをzipinfoして次のようにnodejsディレクトリが含まれていればOK。

$ zipinfo nodejs.zip |head
Archive:  nodejs.zip
Zip file size: 317622 bytes, number of entries: 167
drwxr-xr-x  2.1 unx        0 bx stor 19-Mar-28 12:22 nodejs/
drwxr-xr-x  2.1 unx        0 bx stor 19-Mar-28 12:22 nodejs/node_modules/
drwxr-xr-x  2.1 unx        0 bx stor 19-Mar-28 12:22 nodejs/node_modules/sqlstring/

あとはこれをLambdaのコンソールからレイヤーとして登録し、関数のDesignerとのころでLayersに登録して紐付ければデプロイパッケージに含めずともrequireできるようになる。
他の関数から再利用することも出来てグッド。

参考: AWS ドキュメント » AWS Lambda » 開発者ガイド » AWS Lambda 関数の設定 » AWS Lambda レイヤー
AWS Lambda レイヤー