Angular
lambda
ionic
ServerlessFramework
NestJS

Ionic/Angularと相性抜群のNodeフレームワーク「NestJS」をLambdaで公開する方法

Ionic/Angularでは、TypeScriptを採用しているので、APIからのレスポンスを型定義します。で、常々、「バックエンドでも型定義をして、それをフロントエンドと共有できたら最強では」と思っていたのですが、先日Angularから強い影響を受けたTypeScript製Node.jsフルスタックフレームワーク「NestJS」の存在を教えてもらいました。

どのようなものかは 【Node.js】TypeScript製Node.jsフルスタックフレームワーク Nest 導入編をご覧ください。

これを採用したことにより、今はInterfaceをフロントエンド・バックエンドで共有できていて、とても快適に開発を進めていたのですが、「いざ公開」の段になって、Lambda + API Gatewayで苦戦したのでまとめておきます。


Lambdaで公開する手順

Serverless Framework経由にLambdaに公開する設定については https://github.com/rdlabo/serverless-nestjs でパッケージ一式で公開しています。


既存のプロジェクトに設定する方法


1. Serverless FrameworkとLambda用のパッケージを追加

$ npm install aws-lambda aws-serverless-express express


2. Lambda関数用の src/index.ts を作成


src/index.ts

import { Context, Handler } from 'aws-lambda';

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Server } from 'http';
import * as serverless from 'aws-serverless-express';

const express = require('express')();
let cachedServer: Server;

function bootstrapServer(): Promise<Server> {
return NestFactory.create(AppModule, express)
.then(app => app.enableCors())
.then(app => app.init())
.then(() => serverless.createServer(express));
}

export const handler: Handler = (event: any, context: Context) => {
if (!cachedServer) {
bootstrapServer().then(server => {
cachedServer = server;
return serverless.proxy(server, event, context);
});
} else {
return serverless.proxy(cachedServer, event, context);
}
};


通常公開と違い、Lambdaの関数としてNestJSを利用するので、専用の公開ファイルを用意する必要があります。


3. Serverless Framework設定ファイルの serverless.yml を追加


serverless.yml

service: serverless-nestjs

provider:
name: aws
runtime: nodejs8.10
region: ap-northeast-1

package:
exclude:
- .git/**
- src/**
- test/**
- nodemon.json
- README.md

functions:
index:
handler: dist/index.handler
events:
- http:
cors: true
path: '/'
method: any
- http:
cors: true
path: '{proxy+}'
method: any


regionは、東京で設定します。また、先ほど作成したLambda用関数を、Lambdaに紐つけるために、functionsを設定します。NestJS内でのルーティングをLambda経由で反映させるために path: {proxy+} をトップディレクトリとは別に設定します。


デプロイ方法

$ npm run prestart:prod

$ sls deploy

npm run prestart:prodを実行すると、src/フォルダからtscを使ってdistファイルを生成します。そのあと、Serverless Frameworkのコマンドを叩いてデプロイを実行してください。

うまくいくと、 https://mmjdx4zxmc.execute-api.ap-northeast-1.amazonaws.com/dev/ ができます。


おまけ

IonicとNestJSのInterfaceをどうやって共有するかについては、こちらで「どうしたらいいかなぁ」とツイートしておりますのでご参考になりましたら幸いです。これがベストプラクティスだ!!っていうのありましたらコメントかリプライでご教示いただけましたら幸いです。

https://twitter.com/rdlabo/status/1031760620654276608