JavaScriptNode.jsTypeScript

Serverless Frameworkで作ったNode.jsプロジェクトをTypeScriptへリプレイスする

基本的にServerless FrameworkでAPIや処理系等を実装しているのですが、同梱するライブラリが増えてくるとどうしてもデプロイサイズが気になってきます。 webpackでビルドしてサイズを減らすことも考えた […]

広告ここから
広告ここまで

基本的にServerless FrameworkでAPIや処理系等を実装しているのですが、同梱するライブラリが増えてくるとどうしてもデプロイサイズが気になってきます。

webpackでビルドしてサイズを減らすことも考えたのですが、どうせならTypeScriptに段階的に切り替えてみようかなと思ったのでトライしました。

準備

まずはマイグレーション対象のプロジェクトを作りましょう。

$ sls create -t aws-nodejs -p sls-migration
$ cd sls-migration
$ sls deploy
Service Information
service: sls-migration
stage: dev
region: us-east-1
stack: sls-migration-dev
api keys:
  None
endpoints:
  None
functions:
  hello: sls-migration-dev-hello

素のままだとファイル削減の効果も見えにくいので、SDKをいくつか入れて重しにしておきます。

$ npm init -y
$ npm i -S ask-sdk watson-developer-cloud
$ sls deploy function -f hello
Serverless: Packaging function: hello...
Serverless: Excluding development dependencies...
Serverless: Uploading function: hello (11.34 MB)...
Serverless: Successfully deployed function: hello

11MB。いい感じです。選んだSDKはAWS SDK以外で使ったり興味があったりするもので、特に他意はありませんのでご了承ください。

$ sls invoke -f hello -d '{"key": "value"}'
{
    "statusCode": 200,
    "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":{\"key\":\"value\"}}"
}

動作も問題ない様子です。

TypeScriptを導入する

ここからいよいよTypeScriptを入れていきます。ここからはビルドしたものをデプロイする形になりますので、そのあたりの処理も入れる必要があります。

幸いsls createのテンプレートにaws-nodejs-typescriptがありますので、ここから部品を取る形で進めます。

$ cd ../
$ sls create -t aws-nodejs-typescript -p ts-sls
$ cd ts-sls
$ tree -L 1 -I node_module
.
├── handler.ts
├── package.json
├── serverless.yml
├── source-map-install.js
├── tsconfig.json
└── webpack.config.js

0 directories, 6 files

source-map-install.js, tsconfig.js,webpack.config.jsが新しく追加されています。また、package.jsonを見るといくつかのライブラリが含まれています。

$ cat package.json  | jq .devDependencies
{
  "@types/aws-lambda": "8.10.1",
  "@types/node": "^8.0.57",
  "serverless-webpack": "^5.1.1",
  "source-map-support": "^0.5.6",
  "ts-loader": "^4.2.0",
  "typescript": "^2.9.2",
  "webpack": "^4.5.0"
}

これらを先ほどのプロジェクトに入れていきましょう。

# プロジェクトに戻る
$ cd ../sls-migration

# ライブラリインストール(webpackは5系を入れるとうまく行かないので要注意)
$ npm i -D serverless-webpack source-map-support ts-loader typescript webpack@4

# ファイルをコピー
$ cp ../ts-sls/source-map-install.js ./
$ cp ../ts-sls/webpack.config.js ./
$ cp ../ts-sls/tsconfig.json ./

また、serverless.ymlを開いて以下の2行を追加しましょう。

plugins:
  - serverless-webpack

これでTypeScript(+webpack)を使う準備ができました。この状態でデプロイすると、webpackによるビルドが実行されます。

$ sls deploy function -f hello
<中略>
 @ multi ./source-map-install.js ./handler.js
Serverless: Packaging function: hello...
Serverless: Uploading function: hello (2.15 MB)...
Serverless: Successfully deployed function: hello

2.15MBまで減りましたね。およそ1/5。これだけでも十分に大きいのですが、せっかくなのでTypeScriptの力を借りてみましょう。

TypeScriptのハンドラーを追加する

ここまででは、TypeScriptをビルドに使用していますが対象となるファイルがない状態です。ですので.tsファイルを追加してみましょう。

$ vim handler2.ts
'use strict';
module.exports.hello = async (event, context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event
    }),
  };
};

まずは先ほどのhandler.jsに書いている内容をそのままコピーします。これだけでは対象ファイルに含まれませんので、serverless.ymlにも定義を追加しましょう。

functions:
  hello:
    handler: handler.hello
  hello2:
    handler: handler2.hello

これでTypeScriptファイルもビルドされるようになります。また、tsconfig.jsonを以下のようにすることでより厳密なチェックを受けることが可能です。

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es6",
    "lib": [
      "esnext"
    ],
    "strict": true,
    "moduleResolution": "node"
  },
  "exclude": [
    "node_modules"
  ]
}

strictをtrueにすると、webpackのビルドがこけるようになります。

$ sls deploy
ERROR in /Users/develop/sandbox/sls-migration/handler2.ts
./handler2.ts
[tsl] ERROR in /Users/develop/sandbox/sls-migration/handler2.ts(2,31)
      TS7006: Parameter 'event' implicitly has an 'any' type.

ERROR in /Users/develop/sandbox/sls-migration/handler2.ts
./handler2.ts
[tsl] ERROR in /Users/develop/sandbox/sls-migration/handler2.ts(2,38)
      TS7006: Parameter 'context' implicitly has an 'any' type.

  Error --------------------------------------------------

  Webpack compilation error, see above

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information -----------------------------
     OS:                     darwin
     Node Version:           10.1.0
     Serverless Version:     1.32.0

「引数に型が付いてないぞ!」ということなので、追加してやりましょう。

$ npm i -D @types/aws-lambda @type/node

handler2.tsも以下のように変更します。

import { APIGatewayEvent, Handler } from 'aws-lambda';
export const hello: Handler = async (event: APIGatewayEvent) => ({
  statusCode: 200,
  body: JSON.stringify({
    message: 'Go Serverless v1.0! Your function executed successfully!',
    input: event
  })
})

eventに設定する型は使用するイベントによって変わります。今回のサンプルはAPI Gatewayのバックエンドとして利用するものを設定しました。

これで再度deployを実行すると、今度はエラーなくビルドが成功します。

おわりに

allowJs の設定をしていない状態ですが、今のところこの状態のままでJS / TypeScriptの共存が可能な様子です。

段階的に移行するということが可能ですので、ファイルサイズが気になったり型が欲しいなと思った方はぜひお試しください。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts