最近は以下の組み合わせでLambda関数を書いている
- AWS Lambda (Node 4.3)
- Serverless Framework
- serverless-webpack + babel + eslint
- Yarn
参考
ベースは以下のリポジトリを参考にした。
https://github.com/americansystems/serverless-es6-jest
package.json
テンプレはこんな感じ。
{
"name": "your-service",
"version": "0.0.1",
"dependencies": {
"babel-polyfill": "^6.20.0",
"babel-runtime": "^6.20.0",
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.10",
"babel-plugin-transform-async-to-generator": "^6.16.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-stage-0": "^6.16.0",
"eslint": "^3.14.1",
"eslint-loader": "^1.6.1",
"json-loader": "^0.5.4",
"serverless-webpack": "^1.0.0-rc.3",
"webpack": "^1.14.0",
"webpack-node-externals": "^1.5.4"
},
"license": "MIT",
"engines": {
"node": ">=4.3.0"
}
}
Serverless
デプロイにはServerlessを使用している。Lambdaに特化しているという点でApexも気になるが、今のところはServerlessで不自由していない上にTerraformに馴染みがないのでこちらを使用している。
設定のテンプレは大体下のような感じ。
service: your-service-name
frameworkVersion: ">=1.4.0"
plugins:
- serverless-webpack
provider:
name: aws
runtime: nodejs4.3
stage: prod
region: ap-northeast-1
iamRoleStatements: # IAMの権限が必要であれば
- Effect: "Allow"
Action:
- "cloudwatch:GetMetricStatistics"
Resource: "*"
custom:
webpackIncludeModules: true # enable auto including modules
functions:
yourFunctionName:
handler: handler.main
description: Your function description.
events:
- schedule: # 定期的に実行したい場合
name: your-schedule
description: 'Your schedule description'
rate: cron(0/10 22-15 * * ? *)
enabled: true
memorySize: 128
environment: # 環境変数はコンソール側から指定している。
SLACK_WEBHOOK: set_slack_webhook
Lambdaの環境変数を設定する箇所についてはローカルの環境変数から動的に設定することも可能そうだが、今のところそこまでやっていない。
よくIAMのPolicyにCloudWatch Logsの権限を振り忘れてログ出ね―ってハマる人がいるらしいが、serverlessはデフォルトのIAM Roleに設定してくれるようで、幸いそこにハマったことはなかった。
Webpack
serverless-webpackというプラグインがあるのでこれを使用している。webpack(babel)を通している理由はasync-awaitを使いたいだけ。なのでnpmも可能な限りPromise対応のものを選ぶ。
eslintも入れておくとJSの構文エラーや使用していない変数や関数を教えてくれたりするので便利。
なお、serverless-webpackを使用するとLambda関数毎にデプロイする serverless deploy --function
は使えなくなるらしい。(1つのJSファイルにまとめられることに起因すると思われる。)
var nodeExternals = require('webpack-node-externals');
module.exports = {
entry: './handler.js',
target: 'node',
externals: [nodeExternals()],
module: {
loaders: [
{
test: /\.js$/,
loaders: [
'babel',
'eslint-loader'
],
include: __dirname,
exclude: /node_modules/,
},
{
test: /\.json$/,
loaders: ['json']
}
]
}
};
{
"plugins": [
"transform-runtime",
"transform-async-to-generator"
],
"presets": ["es2015", "stage-0"]
}
module.exports = {
"parser": "babel-eslint",
"extends": ["eslint:recommended"],
"plugins": [],
"parserOptions": {
"ecmaVersion": 6
},
"env": {
"node": true,
"es6": true
},
"globals": {},
"rules": {
"no-console": "off",
"strict": 0
}
};