VSCodeでBolt for TypeScriptをホットリロード+デバッグ実行させてみよう


はじめに

HAL大阪Web開発専攻4年の小澤です。現在、内定先である株式会社タンバリンにてアルバイトをしています。
@k-gen さんと同じく、@75asa さんにお誘いいただき今回参加に至りました。

内定先の社内OSSである分報管理ツールの開発に参加した際、
SlackAPI(Bolt)初心者の自分にも何かできることが無いかを探した末に見つけたアイデアを今回記事にしようと思い立ちました。
対戦よろしくお願いします。

使うライブラリ, アプリケーション

  • VSCode
  • Bolt for TypeScript
    • nodemon
    • ts-node
  • ngrok

(tsファイルをトランスパイル後のjsファイルが入るディレクトリは./lib)

なぜ ts-node-dev じゃなくて ts-node + nodemon (+ tsc) を使うのか

ts-nodeのホットリロード対応版であるts-node-devでデバッグ実行(inspectモード)をした場合、
.tsファイルのsourceMapが生成されない為か、トランスパイル後の.jsファイルがデバッガの走査対象となってしまいまともに使えませんでした。(2020/10時点)

ts-nodeでデバッグ実行をした場合は.tsファイルがデバッガの走査対象となるので、
それ+αでホットリロードを効かせる為にtscとts-nodeをnodemonでラップさせる構成にしました。

VSCode(デバッガ)側の設定

.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [{
    "name": "Attach to Bolt",
    "type": "node",
    "request": "attach",
    "port": 9229,
    "address": "localhost",
    "localRoot": "${workspaceFolder}/lib",
    "protocol": "inspector",
    "outFiles": ["${workspaceFolder}/lib/**/*.js"],
    "trace": true,
    "restart": true
  }]
}

リポジトリ側の設定

ホットリロード設定

nodemon.json
{
  "watch": [
    "src"
  ],
  "ext": "ts",
  "exec": "ts-node ./src/index.ts"
}

ホットリロード及びinspectコマンド設定 (npm run devの部分)

package.json
{
  ...
  "scripts": {
     "dev": "nodemon -L -w src -e ts -x \"tsc && node --require dotenv/config --inspect=localhost:9229 --experimental-modules lib/index.js\"",
  },
  "devDependencies": {
    "@types/eslint": "^7.2.1",
    "@types/node": "^14.6.0",
    "@typescript-eslint/eslint-plugin": "^3.9.1",
    "@typescript-eslint/parser": "^3.9.1",
    "eslint": "^7.7.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-prettier": "^3.1.4",
    "nodemon": "^2.0.4",
    "prettier": "^2.0.5",
    "ts-node": "^9.0.0",
    "typescript": "^4.0.2"
  },
  "dependencies": {
    "@slack/bolt": "^2.3.0",
    "dotenv": "^8.2.0",
  }

デバッグ実行してみる

アプリ起動準備 ~ アプリ起動

ngrokを使ってBoltアプリを外部公開します。

$ ngrok http 3000
ngrok by @inconshreveable                                                                                                                                                                       (Ctrl+C to quit)

Session Status                online
Session Expires               6 hours, 46 minutes
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://<random>.ngrok.io -> http://localhost:3000
Forwarding                    https://<random>.ngrok.io -> http://localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              6       0       0.00    0.00    7.15    70.19

SlackAPIアプリケーションのEvents Scripts/Enable Events/New Request URLに、
http://<random>.ngrok.io/slack/eventsを貼り付けます。
(画像内の場合: http://490f5c7ea13e.ngrok.io/slack/events)

Boltアプリを起動します。

$ npm run dev
> [email protected] dev /Users/tk_zawa/slack_bot
> nodemon -L -w src -e ts -x "tsc && node --require dotenv/config --inspect=localhost:9229 --experimental-modules lib/index.js"

[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts
[nodemon] starting `tsc && node --require dotenv/config --inspect=localhost:9229 --experimental-modules lib/index.js`
Debugger listening on ws://localhost:9229/c8be65d7-dfc5-49c1-9991-956983e748bf
Debugger listening on ws://localhost:9229/c8be65d7-dfc5-49c1-9991-956983e748bf
For help, see: https://nodejs.org/en/docs/inspector
[DEBUG]  web-api:WebClient:0 initialized
[DEBUG]  web-api:WebClient:0 apiCall('auth.test') start
[DEBUG]  web-api:WebClient:0 will perform http request
⚡️ Bolt app is running!
[DEBUG]  web-api:WebClient:0 http response received

デバッガ起動


↑の▶を押すと、Boltを実行中のターミナル内で以下のようなメッセージが出ます。(inspect成功)

Debugger attached.
Debugger listening on ws://localhost:9229/<random>
Debugger listening on ws://localhost:9229/<random>
For help, see: https://nodejs.org/en/docs/inspector

ブレークポイント設定 ~ 変数確認

デバッガを起動する前もしくは起動中に、任意の場所でブレークポイント(赤い●)を設定します。

アプリで設定しているSlackのアクションに対応する行動(今回はメッセージ投稿)を取ります。

すると、VSCode側のデバッガのサイドバーが更新され、生成済みの変数の中身が見れるようになります。

欲しい変数があれば、右クリックで出てくる「式としてコピー」を押すことで、message.textの形で取得できます。