tl;dr

ES2015 で Lambda Function を書いて、 Babel でビルドして Apex でいい感じにデプロイするよ。ソースはここ

登場人物

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.jsbabel-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 の相性が悪いっぽい

あたりです。

元記事はこちら

手っ取り早く ES2015 で Lambda Function を書く