Engineer's Way

主にソフトウェア関連について色々書くブログです。

AWS LambdaをNode.jsで簡単に作れるサーバレスアーキテクチャのフレームワークClaudia.jsを実戦で使ってみた

 

f:id:matsnow:20170525010920p:plain:w200

はじめに

今のプロジェクトでAWS Lambdaによるサーバレスアーキテクチャのシステムを開発していますが、フレームワークとしてClaudia.jsというものを選択してみました。

Claudia.jsとは

AWS Lambdaのようなサーバレスアーキテクチャ用のフレームワークとしてはServerless Frameworkが有名ですが、
それ以外にClaudia.jsというフレームワークがあります。 claudiajs.com

以下のような点がServerlessとの大きな違いです。

  • Claudia.jsはAWS Lambda、かつNode.js (JavaScript、TypeScript)に特化している。 特化している分、非常に少ない手間でデプロイまでできる。
  • api-builderやbot-builderなどの追加パッケージを使うことで、簡単にAPIBotを作れる。

なお、サーバレスアーキテクチャということもあり、フレームワークといっても、
フルスタックやMVCなどではなく、むしろビルド・デプロイツールといった色合いが強いです。

Claudia.jsの導入

Claudiaの導入は以下のブログが分かりやすいです。 qiita.com

dev.classmethod.jp

あとは公式のサンプル集を見れば、たいていのものは作れると思います。(手抜き) github.com

実際に使ってみる

Claudia.jsはLambdaやAPIをNode.jsを書いていく上では非常に便利ですが、 実戦投入するに当たって、いくつか考慮する点があります。

1. package.jsonは関数ごとに用意する

公式のサンプルなどでは、ディレクトリは1階層だけで、そこにpackage.jsonが置いていますが、実開発ではディレクトリは複数階層になることが多いと思います。
例えば、以下のようなディレクトリ構成にする場合、api/hello、function/foo、function/hogeの各ディレクトリにpackage.jsonが必要です。

sample  
├── api  
│   └── hello  
│       └── index.ts  
└── function  
    ├── foo  
    │   └── index.ts   
    └── hoge  
        └── index.ts  

その時のpackage.jsonの内容は、例えば「function/foo/package.json」であれば、以下のようになります。
nameがLambda関数の名前、descriptionは説明文、mainはエントリポイントのJSファイルです。

{
  "name": "foo",
  "description": "Lambda関数のサンプル",
  "main": "index.js"
}

なお、node_modulesのディレクトリは下位階層には不要です。 通常のプロジェクトと同じくトップにあればOKです。

2. ロールはあらかじめ作成しておく

Claudia.jsのコマンドでは、とりあえず以下を指定すればLambda関数を作成できます。 sh $ claudia create --region ap-northeast-1 --handler index.handler ただし、この場合、Claudia.jsによってIAMロールが毎回新しく作られてしまいます。 そのため、あらかじめLambda用のIAMロールを作成し、「–role sample-role」のように指定するようにした方が良いです。

3. claudia create –handlerの指定は相対パス

単純なことですが、–handlerで指定するハンドラ関数はディレクトリ構成が影響します。 例えば、src/ の下にindex.jsを入れており、「export handler」としている場合、「–handler src/index.handler」と指定する必要があります。

4. api-builderの中でpromiseを扱うときはpromiseをreturnする

ハマりどころの1つとして、API作成時にPromiseを使う場合、それをreturnしないと、 CloudWatchLogsなどにも何も出力されないまま、APIが終了します。

api.post('/user', function (request) {
    return dynamoDb.put({
        TableName: request.env.tableName,
        Item: {  userid: request.body.userId }
    }).promise();
}); 

公式ドキュメントの「4. Return a Promise out of the API handler」に記載されていますが、 かなりハマりやすい点なので注意が必要です。 https://claudiajs.com/tutorials/external-services.html

まとめ

最初に慣れるまでは若干手間取るかもしれませんが、一度使い方を覚えれば非常に楽に開発が進められる、良いフレームワークだと思います。
とりあえず、今のプロジェクトでは、このままClaudia.jsを使い続けるつもりです。