このページは Wanoグループ Advent Calendar 2016 の3日目の記事となります。
ギリギリになってしまった。
Serverless Framewok v1.1 でtypescript & babelなベースを整えるとこまでやったのでメモっておきます。
S3の静的サイトホスティング以外でのどケチなサイト運営を模索していきたい。
今回は jsonを返すデモ と HTMLを返すデモを作るとこまで目指します。
serverless frameworkでのプロジェクトセットアップ
serverless create プロジェクト名
でプロジェクトのひな形を作っておきます。
プロジェクトの設定で、webpackプラグインやbabel,typescriptを適用するためのモジュールをインストールします。
npm install babel-loader babel-core babel-preset-es2015 ntypescript serverless-webpack ts-loader
serverless コマンドでプロジェクトを作ったあと、serverless.ymlで
プロジェクトの設定を行います。
書いてないけどLambda関数のタイムアウト時間やメモリ設定もここ。
service: serverless-webpack-advent-demo
plugins:
- serverless-webpack # ここでプラグインを指定します
provider:
name: aws
runtime: nodejs4.3
stage : production
profile: xxxx # aws-cliにおけるprofileを設定します。
regeon : ap-northeast-1
functions:
apiDemo:
handler: handler.apiDemo # 動かすlambda関数名
events:
- http:
method: get
path: apiDemo
response:
headers:
Content-Type: "'application/json'"
template: $input.path('$')
htmlDemo:
handler: handler.htmlDemo # 動かすlambda関数名
events:
- http:
method: get
path: htmlDemo
response:
headers:
Content-Type: "'text/html'"
template: $input.path('$')
webpack設定
serverless-webpack
webpackプラグインが入ったので、ビルド段階で typescriptやbabelを通して、AWS lambda上のnodejs4.3で使えない段階の機能にも対応できるようにしておきます。
個人的にgulpやgrunt等のタスクランナーはすぐに使わなくなりましたが、
webpackはビルド速度の速さや cssの多段sourcemap作成のためにもとても便利なので、しばらく離れられそうにないです。
また,serverless-webpackは
serverless webpack serve
してサーバーを動かすことで、ローカルでapi gateway + lambdaのテストもできます。
development.webpack.config.js
const path = require('path');
module.exports = {
entry: './ts/handler.ts',
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: 'handler.js'
},
target: 'node',
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
},
module: {
loaders: [
{
test: /\.ts(x?)$/, // .ts or .tsx にフックさせてbabelやtypescriptを動かす
exclude: /node_modules/,
loader: 'babel-loader?presets[]=es2015!ts-loader'
}
]
},
ts: {
compiler: 'ntypescript'// 最新版のtypescriptもts-loaderで使えるように入れておきます
}
};
typescript設定
tsconfig.json を書きます。webpackでts-loaderを書く場合、コンパイル時の設定としてここを見に来るようになります。
{
"compilerOptions": {
"module": "commonjs",
"removeComments": true,
"target" : "es6",
"allowJs" : true,
"pretty" : true,
"noImplicitThis" : true,
"jsx" : "react",
sourceMap": true"
}
}
エントリーポイントになるhandler.ts
serverless.ymlで定義したLambda関数の実装を作ってみます。
非同期チェーンの記述に便利な async/await も使えるようになったので意味もなく試しておきます。
TypeScriptって言っといて今回は型がガバガバです。
export const apiDemo = (event, context, callback) => {
const response = {
headers: {
"Content-Type":"application/json"
},
statusCode: 200,
body: JSON.stringify({
message: 'TypeScriptでコンパイルしますた'
}),
};
if (context.succeed != null){
context.succeed(response); //<= LAMBDA-PROXYとしてAPIを作成するときはこっちを使わないといけない。
} else {
callback(null , JSON.parse(response.body));
}
};
export const htmlDemo = (event , context , callback) => {
const response = {
headers: {
"Content-Type":"text/html"
},
statusCode: 200,
body: `
<html>
<head>
<meta charset="utf-8">
<title>lambda html sample</title>
</head>
<body>
<div id="content">
デモ
</div>
</body>
</html>
`
};
// test
(async()=>{
await new Promise((resolve)=>{
setTimeout(resolve, 1);
});
if (context.succeed != null){
context.succeed(response);
} else {
callback(null , response.body); // <-- でもHTML返すときはこっち使うみたい
}
})();
};
ローカルでのテスト
前述の serverless-webpack の機能を使ってローカルでコンパイルの自動化とブラウザ上のテストができるようにしておきます。
この手のシェルスクリプトは npm scriptとしてpackage.jsonに記述して便利にしておきます。
package.json
{
....(略)
"scripts": {
"watch": "./node_modules/.bin/webpack --watch",
"serve": "serverless webpack serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
....(略)
これで
npm run watch
でコードの自動的な差分ビルドができ、
npm run serve
でローカルサーバーが立ち上がります。
あとはこのみで livereload など入れれば、自動でコード変更後のブラウザリロードも行うようになります。
これで
http://localhost:8000/htmlDemo
http://localhost:8000/apiDemo
にアクセスすることで、それぞれの api gateway / lambda function が ローカルで動くようになりました。
デプロイは
serverless deploy
を叩くだけです。
今回はここまでですが、今後 URLのルーティング や テンプレートの読み込み、DynamoDBなどとの連携も模索していこうかと考えています。(Reactのサーバーサイドレンダリングとかもね)