notebook

都内でWEB系エンジニアやってます。

ServerlessFramework(Node.js)のプロジェクトをTypeScriptで書き換える

ServerlessFrameworkでTypeScriptを書こうとすると最初からテンプレートaws-nodejs-typescriptを使えばよかったっぽい。

プラグインはSserverless-webpackを使ってとりあえず試してみた

が、すでに書いてしまったプロジェクトだったので新規で雛形だけ作ってそこに追記していく方法で挑んでみたがローカル実行がうまくいかず

結局serverless-plugin-typescriptにした

prisma-labs/serverless-plugin-typescript: Serverless plugin for zero-config Typescript support

github.com

そのときに躓いた箇所のメモ書き

sls invoke localが失敗する

Serverless: Using local tsconfig.json
Serverless: Typescript compiled.
/home/vagrant/site-search/backend/.build/tshandler.js:10
import { readFileSync } from 'fs';
^^^^^^

SyntaxError: Unexpected token import
  • tsconfig.json

tsconfigmodulecommonjsを追加した

"module": "commonjs"
  • 参考

TypeScriptで"SyntaxError: Unexpected token import"になったときの解決方法

blog.zuckey17.org

インストール

npm install -D serverless-plugin-typescript typescript

粛々と書き換える

handlerで指定する箇所は下記の様に書き換えた

- exports.run = async (event, context) => {
+ export const run: APIGatewayProxyHandler = async(event, context) => {

Layerと合わせたデプロイに失敗する

function毎のデプロイは成功するがLayerと合わせたときにうまく行かない模様

  Serverless Error ---------------------------------------

  No file matches include / exclude patterns

servicePathの扱いが上手く行ってないみたい

それによってInclude, Excludeの処理でエラーを吐いてしまうようになった模様

ちょっと追ってみただけだとよくわからなかったのでプロジェクト固有のパッチを当てて対応した

Layerの場合はprefixがつく(pathを指定している)のでそれを元にservicePathを変える分岐を入れている

  • serverless.yml(一部抜粋)
plugins:
  - serverless-plugin-typescript
layers:
  puppeteer:
    path: puppeteer_layer_dist/
    name: puppeteer
functions:
  run:
    handler: tshandler.run
    layers:
      - {Ref: PuppeteerLambdaLayer}
  • node_modules/serverless/lib/plugins/package/lib/packageService.js
    // NOTE: please keep this order of concatenating the include params
    // rather than doing it the other way round!
    // see https://github.com/serverless/serverless/pull/5825 for more information

+    const rootDir = this.serverless.config.serverlessPath.replace(/\/node_modules\/serverless\/lib/, '');
+    if (prefix && prefix.match(/puppeteer_layer_dist/)){
+      this.serverless.config.servicePath = `${rootDir}`;
+    }
+    else {
+      this.serverless.config.servicePath = `${rootDir}/.build`;
+    }
    return globby(['**'].concat(params.include), {
      cwd: path.join(this.serverless.config.servicePath, prefix || ''),
      dot: true,
      silent: true,
      follow: true,
      nodir: true,
    }).then(allFilePaths => {

patchは下記方法で当てた

patch-packageでpatchをコード管理する - notebook

swfz.hatenablog.com

おわり

そんなコード量は多くなかったので書き換え自体はサクサクいけた

ビルド時のcurrent path的なものが変わるのとjsonファイルを移動してくれなかったのでcongig的なファイルをtsに書き換えたりもした

あまり納得行ってないので時間とれたらなんとかしたい

どうしてもフレームワーク周りで躓くことが多いのでローカル実行だけ確認できたらあとはaws-cliで投げるだけのスクリプト書いたほうが早いんじゃないかと思えてきた。。。