Serverless Frameworkでデバッガーを使ってデバッグする(Node.js)

Serverless Frameworkで開発を行う際、ローカルでデバッガーを使いたかったので調査しました。 試行錯誤しながらなんとか処理をブレークポイントで止めることができるようになったので、いろいろ抜けてる部分とか無駄な部分もあるかも知れませんが作業メモを残します。

参考資料

公式ドキュメント

www.serverless.com

YouTube動画

そもそもServerless Frameworkでデバッガー使えるかよくわからなかったので、作業前に実際に動いてる動画を確認できて有り難かったです。
www.youtube.com

実行コマンドメモ

作業で実行したコマンドは以下。

sls create --template aws-nodejs --path myService

Node.jsのテンプレートを使用してプロジェクトを新規作成。

npm install --save-dev serverless-offline

デバッグ用のプライグインであるserverless-offlineをインストール。

ディレクトリ構成

コード

.devcontainer/devcontainer.json

{
    "name": "Node.js & TypeScript",
    "image": "mcr.microsoft.com/devcontainers/typescript-node:0-18",
    "features": {
        "ghcr.io/devcontainers/features/aws-cli:1": {},
        "ghcr.io/devcontainers-contrib/features/serverless:1": {}
    }
}

.vscode/launch.json

Serverless Frameworkの公式ドキュメントを引用。

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Serverless Offline",
      "cwd": "${workspaceFolder}",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "debug"],
      "sourceMaps": true
    }
  ]
}

myService/package.json

scriptsの記述はServerless Frameworkの公式ドキュメントから引用。

{
  "devDependencies": {
    "serverless-offline": "^12.0.2"
  },
  "scripts": {
    "debug" : "export SLS_DEBUG=* && node --inspect /usr/local/share/npm-global/bin/serverless offline"
  }
}

serverless.yml

pluginsにserverless-offlineを指定しています。

service: myservice

frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs18.x

  region: ap-northeast-1


functions:
  hello:
    handler: handler.hello

plugins:
  - serverless-offline

handler.js

ほぼテンプレートのままです。

'use strict';

module.exports.hello = async (event) => {
  console.log('test debug')
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Go Serverless v1.0! Your function executed successfully!',
        input: event,
      },
      null,
      2
    ),
  };
};

作業メモ

handler.jsにブレークポイントを設定

package.jsonに表示されるDebugのボタンをクリック

デバッガーがアタッチされた

デバッガーがlocalhostの3002ポートで起動する。 API Gatewayは設定していないのでブラウザからはアクセスできない。

ターミナルを新規に開いて、以下のAWS CLIコマンドでlambdaを実行する。オプションでendpointはlocalhost:3002を向くように設定する。

aws lambda invoke /dev/null --endpoint-url http://localhost:3002 --function-name myservice-dev-hello

上記コマンドを実行するとブレークポイントで処理が止まる。

補足

Serverless Frameworkで用意されてるsls invokeコマンドには--endpoint-urlオプションはなく、オプションをそのまま使うとエラーになる。

$ sls invoke --endpoint-url http://localhost:3002 --function-name myservice-dev-hello

Error:
Detected unrecognized CLI options: "--endpoint-url", "--function-name".

sls invoke localコマンドを使うことでServerless Frameworkの関数をローカルで実行できるが、デバッガーを起動した状態でsls invoke localを実行するとブレークポイントで止まらず、処理が完了した。
おそらくデバッガーが起動している3002ポート以外で処理を受ける形になっていると推測している。

$ sls invoke local -f hello
Running "serverless" from node_modules
test debug
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless v1.0! Your function executed successfully!\",\n  \"input\": \"\"\n}"
}

とりあえずServerless FrameworkのNode.jsランタイムでデバッガーを使うことができました。