tl;dr
ES2015 で Lambda Function を書いて、 Babel でビルドして Apex でいい感じにデプロイするよ。ソースはここ。
登場人物
- ES2015 (ES6)
- Apex
- 複数の Lambda Function のデプロイを大幅に簡略化してくれるツール。 Apex 自体は Node.js に特化しているわけではなく、他言語の function もデプロイできる
- Babel
- 先進的な記述の JavaScript を幅広い処理系で実行可能なようにコンパイルしてくれるツール
- Apex.js (node-apex)
- Lambda Function を書く上でのお作法(
context
オブジェクトの処理)をラップしてくれる薄いライブラリ
- Lambda Function を書く上でのお作法(
ES2015 でLambda Function を書く
こんなのです。 import
とか let
とかアロー関数とかテンプレートリテラルとかとか、まあ ES2015 ですよね。
index.js
import λ from 'apex.js' import 'babel-polyfill' export default λ((e, ctx) => { let message = `Hello ${e.name}, I am a Lambda function "${ctx.functionName}"!`; return({ "message": message }); });
λ
ってなんだ?
これは先述のApex.js (node-apex)をこの名前で呼んでいるだけです。何故こんな名前を?と思いますが、深く考えないでおきます。
便利ですが、あくまでヘルパーなので必須ではありません。
必要ランタイムのインストール
$ npm install apex.js babel-polyfill --save
Hello world なのでこれだけですが、やりたい事に応じてdependencies
に追加しましょう。
Babel を使う準備
Babel をインストールする
$ npm install babel-cli babel-preset-es2015 --save-dev
これはデプロイされた Lambda Function 上では必要にならないのでdevDependencies
でよいです。
コンパイル前後のファイル配置
今回は以下のような配置にすることにしました。
├── functions │ └── hello │ ├── lib # Babel によりコンパイルされた出力ファイルが設置される │ └── src # ここに ES2015 で記述したファイルを設置する ...
Babel の設定ファイルを置く
.babelrc
{ "presets": [ "es2015" ] }
Apex を使う準備
Apex 最高。 npm モジュール込みのデプロイは、手動だと zip したりが面倒過ぎて死にます。
Apex をインストールする
Apex 自体は Go で実装されたツールですが、 apex-binというバイナリラッパーを使うことで node_modules
以下にインストールして使用可能な状態にすることができます。
$ npm install apex-bin --save-dev
これdevDependencies
でよいです。
Apex の設定を書く
Apex の動作には以下のようなファイル構造が最低限必要です。
├── functions # 一連の Lambda Function 群が配置されているディレクトリ │ ├── hello # 「hello」という名前の function │ │ └── ... # 「hello」という名前の function のスクリプト本体と付随するファイル │ ├── ... │ └── project.json # 一連の Lambda Function 群のデプロイ設定などを記述するファイル
project.json
の中身は次のように設定します。
project.json
{ "name": "es2015-lambda", "description": "ES2015 example", "role": "arn:aws:iam:: <12桁のAWSアカウントID >:role/", "runtime": "nodejs4.3", "handler": "lib.default", "timeout": 10, "hooks": { "build": "cp ../../package.json . && npm install --production && babel src -d lib", "clean": "rm -rf lib node_modules package.json" } }
ほとんど書いてあるままですが、hooks.build
が重要です。ここに Babel を使って ES2015 を ES5 に変換するコマンドを入れておくことで、apex deploy
を実行する際にそれが自動で事前に発動します。hooks
の実行ディレクトリは各 function 以下です。
他に工夫してある点としては、package.json
を一度各 function 以下にコピーしてからnpm install --production
しているところです。これによりデプロイされた Lambda Function 上で必要になるパッケージ(今回は apex.js
とbabel-polyfill
)のみが Apex により同梱されてデプロイされます。
できたのがこちら
デプロイする
$ npm run deploy
credentials がないと言われたらここらへんを、リージョンの設定がないと言われたらAWS_REGION=
を追加しましょう。
動作を試す
Apex にはapex invoke
でfunction をコマンドライン上から叩く機能があります。サンプルではそれを npm run test
でラップしてあります。
$ AWS_REGION=ap-northeast-1 npm run test > es2015-lambda@0.0.1 test /Users/yamaguchi/Repositories/es2015-lambda > cat event.json | apex invoke hello {"message":"Hello Yoriki, I am a Lambda function \"es2015-lambda_hello\"!"}
おお、動いている。
余談
Apex のリポジトリには Webpack を使って Babel で Lambda Function を書くサンプル が含まれていて、本記事の内容はほとんどこのサンプルのパクリです。
Webpack を使わず babel-cli でやってみた理由としては
- Lambda はブラウザでなくれっきとした Node.js 環境なので、 全依存ファイルを一まとめする Webpack の動作はオーバーキル気味に感じる
- Webpack と AWS SDK for JavaScript の相性が悪いっぽい
あたりです。