この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。サービスグループの武田です。
先日Serverless Framework+JavaScript環境に、serverless-layersプラグインを導入し、お手軽にnode_modulesをLambda Layers化しました。
Serverless Frameworkのserverless-layersプラグインを使って超お手軽にnode_modulesをAWS Lambda Layers化する
今回は同様のことを、TypeScript(+webpack)の環境でもやってみました。
検証環境
次のような環境で検証しています。
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.6
BuildVersion: 18G103
$ node -v
v10.16.3
$ npm ls serverless serverless-layers
example-serverless-ts@1.0.0 /path/to/example-serverless-ts
├── serverless@1.53.0
└── serverless-layers@1.4.2
Lambdaのランタイムはnodejs10.x
です。またAWSにデプロイするためのIAMなどは用意されていることとします。
やってみた
プロジェクト作成
さっそくプロジェクトを作っていきます。テンプレートにaws-nodejs-typescript
を指定すると、TypeScriptが使える環境で作成されます。
$ npx -p serverless sls create -t aws-nodejs-typescript -p example-serverless-ts
$ cd $_ && npm install && npm install -D serverless
$ npx sls invoke local -f hello
{
"statusCode": 200,
"body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!\",\n \"input\": \"\"\n}"
}
またデプロイ先を東京リージョンにするため、provider.region
を追記しておきます。
serverless.yml
provider:
name: aws
runtime: nodejs10.x
region: ap-northeast-1
次にmomentとunderscore.stringをインストールし、モジュールを使うようにhandler.js
を少し改造します。
$ npm install moment underscore.string
handler.ts
import { APIGatewayProxyHandler } from 'aws-lambda';
import * as moment from 'moment';
import { prune } from 'underscore.string';
import 'source-map-support/register';
export const hello: APIGatewayProxyHandler = async (event, _context) => {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!' + prune(moment().format(), 12),
input: event,
}, null, 2),
};
}
確認のため、もう一度ローカル実行してみます。
$ npx sls invoke local -f hello
{
"statusCode": 200,
"body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!2019-10-02T...\",\n \"input\": \"\"\n}"
}
問題なく実行できました。
Layer化せずにデプロイ
Layer化した後とのサイズが比較できるように、一度そのままデプロイしてみます。
$ npx sls deploy
...
Serverless: Uploading service example-serverless-ts.zip file to S3 (366.21 KB)...
$ npx sls invoke -f hello
{
"statusCode": 200,
"body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!2019-10-02T...\",\n \"input\": {}\n}"
}
366.21 KB というサイズでした。実行も問題なくできています。マネジメントコンソールにアクセスしてデプロイされたファイルを確認してみたところ、次のようになっていました。
serverless-layersを導入してデプロイ
続いてserverless-layersを導入していきます。前回とほぼ同じ手順ですが、今回はwebpackのビルド対象からnode_modulesを除外する必要があります。
- Lambda Layersデプロイ用のS3バケットを用意
- serverless-layersプラグインをインストール
- 設定ファイルに設定を追加
- webpackの設定変更
1の手順は省略します。ここではバケット名をlambda-layers-deploy-123456789012
としておきます。
次にsls plugin install
でプラグインをインストールします。
$ npx sls plugin install --name serverless-layers
先ほど作成したバケットを設定ファイルに追加します。
serverless.yml
custom:
serverless-layers:
layersDeploymentBucket: lambda-layers-deploy-123456789012
node_modulesをwebpackのビルド対象から除外します。
$ npm install -D webpack-node-externals
webpack.config.js
const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
entry: slsw.lib.entries,
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
target: 'node',
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{ test: /\.tsx?$/, loader: 'ts-loader' },
],
},
externals: [nodeExternals()],
};
以上で必要な変更は完了です。デプロイしてみましょう。
$ npx sls deploy
Serverless: [LayersPlugin]: Downloading package.json from bucket...
Serverless: [LayersPlugin]: package.json does not exists at bucket...
Serverless: [LayersPlugin]: Dependencies has changed! Re-installing...
...
Serverless: Uploading service example-serverless-ts.zip file to S3 (3.25 KB)...
$ npx sls invoke -f hello
{
"statusCode": 200,
"body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!2019-10-02T...\",\n \"input\": {}\n}"
}
Lambda本体は 3.25 KB とかなり軽量化されました。マネジメントコンソールでファイルを確認すると、きちんと依存モジュールが除外されていることも確認できました。
まとめ
Serverless Framework+TypeScriptの環境でserverless-layersを試してみました。webpackの設定変更が若干見落としがちになりそうです(というか見落としてました)。それではよいServerless生活を!