Nodejs 调试代码二

转载:https://www.jianshu.com/p/6fd5a476d135

调试 Express 代码

初始化 express 工程。

$ mkdir express-demo
$ cd express-demo
$ npm init -y
$ npm install express

  

创建 index.js 文件,内容如下

const express = require('express')
const app = express()

app.get('/', (req, res) => {
    const a = 1
    const b = 2
    const c = a + b
    res.end(`a + b = ${c}`)
})

app.listen('3000', function () {
    console.log('服务器已启动,端口', 3000)
})

 

方法一:request: launch

参考前文 Vscode 调试,添加配置文件如下:

// .vscode/launch.json
{
    "type": "node",
    "request": "launch",
    "name": "Express launch",
    "program": "${workspaceFolder}/index.js"
}

  

express 项目有个入口文件 index.js,平时启动服务需要输入 $ node index.js,调试的时候使用内置的调试器程序启动 index.js。

request: "launch" 表示使用调试器程序启动 index.js 文件。

方法二:request: attach

正常启动 Express 服务。

 
图1

此时突然想调试某个接口,如果使用 launch 方式,需要 Ctrl + C 停掉当前服务,然后用调试器程序重新执行 index.js。但是现在不想重启服务,又要对代码进行调试,可以使用 attach 方式。

添加调试配置文件如下。

// .vscode/launch.json
{
    "type": "node",
    "request": "attach",
    "name": "Express attach",
    "processId": "${command:PickProcess}",
    "port": 9229
}
  • request: "attach" 表示 Nodejs 程序已经在运行着,待会启动调试器程序,去关联这个已经运行的 Nodejs 程序;
  • processId: "${command:PickProcess}" 进程ID,后面花括弧里的东东不用管,意思当你点击 Vscode 调试面板绿色箭头(下图红字1)时会弹出一个下拉框让你选择:调试器程序关联哪一个正在运行的 Nodejs 程序(下图红字2)。
 
图2

我的机器上起了好几个 Nodejs 程序,跑 express-demo 的是第二个 Nodejs 程序,点击之后再看看终端,会打印一些新的消息,其中 Debugger attached 表示调试器程序已经和正在运行的 Nodejs 程序关联起来了。

 
图3

此时在 Vscode 中的源码里打个断点,在浏览器中访问 localhost:3000 可以看到进入断点了。

 
图4

调试 nodemon 代码

还是👆上面 Express 的例子,你会发现改动代码不会立即生效,需要重启服务才行。
第三方包 nodemon 可以监听文件变化,自动重启服务。(supervisor 包作用相同)

全局安装 nodemon:

$ npm install nodemon -g
 

修改 package.json 的 scripts 属性

"scripts": {
    "dev": "nodemon index.js"
}
 

此时执行 npm run dev 即可启动服务,修改 index.js 代码,会发现服务自动重启。

对于 Nodemon 启动的 Express 如何调试呢?

Vscode 打开调试配置,点击 Add Configuration(红字1),选择 Nodemon Setup(红字2)。

 
图5

Vscode 会自动生成一份调试配置文件。(program 属性默认入口文件为 app.js,这里改成我们的 index.js)

{
    "type": "node",
    "request": "launch",
    "name": "nodemon",
    "program": "${workspaceFolder}/index.js",
    "runtimeExecutable": "nodemon",
    "restart": true,
    "console": "integratedTerminal",
    "internalConsoleOptions": "neverOpen"
}

  

 

上面配置文件中前四个属性都有介绍过,这里主要介绍后四个属性的含义。

runtimeExecutable

使用哪个命令运行脚本,这里是 nodemon,启动调试器相当于执行 nodemon index.js。如果没有写 runtimeExecutable 这个属性,它的默认值为 "node"。

这里的 nodemon 需要全局安装,这样在环境变量 PATH 中才能找到该命令。

restart

加上这个配置,修改代码,调试器才会重启。

console

启动调试器后,会打印一些信息,如:调试器服务端监听哪个端口,调试器客户端是否连接上等。

console 配置有三个值,分别设置在什么地方打印这些信息:

  • integratedTerminal:Vscode 集成终端中打印信息,下图 Terminal 选项窗;
  • internalConsole:Vscode 里的调试控制台中打印信息,下图 Debug Console 选项窗;(改成这个吧~)
  • externalTerminal:打开系统自带的终端打印信息;
 
图6

internalConsoleOptions

internalConsole 即 Vscode 中的 Debug Console,在👆介绍 console 配置时已经介绍过了,internalConsoleOptions 设置是否自动打开 Debug Console 选项窗。

  • neverOpen:不会自动跳转到 Debug Console 选项窗,但是可以手动点击切换到 Debug Console 选项窗;
  • openOnSessionStart:即便当前在 Terminal 选项窗,当进行调试时,会自动跳转到 Debug Console 选项窗。
  • openOnFirstSessionStart:下同;

调试 Typescript 代码

上面👆Express 代码都是用原生 js 写的,如果用 Typescript 来写 Express 代码,如何调试呢?

调试之前,先要搭建 Typescript + Express 开发环境,参见 环境搭建

src 目录放 ts 写的代码;
dist 目录放编译后的 js 代码。

前面已经介绍过在 Vscode 中调试 js 代码,但是 ts 编译成的 js 代码丑陋无比,如下:

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var express_1 = __importDefault(require("express"));
var app = express_1.default();
app.get('/', function (req, res) {
    res.send('Hello Ts Express  dd ee ff');
});
app.listen(3000, function () {
    console.log('Server is running.');
});
//# sourceMappingURL=app.js.map

这导致我们想直接在 ts 文件上打断点,而非在 js 文件上打断点,如何做到这一点,是接下来的重点。

打开 Vscode 调试配置文件:

{
    "type": "node",
    "request": "launch",
    "name": "Launch Program",
    "program": "${workspaceFolder}/src/app.ts",
    "runtimeExecutable": "nodemon",
    "restart": true,
    "preLaunchTask": "tsc: build - tsconfig.json",
    "outFiles": ["${workspaceFolder}/dist/**/*.js"]
}

前面 6 个属性都介绍过,只有最后两个属性是陌生的。

preLaunchTask

在调试器启动入口文件之前执行这个任务,这里的任务是 tsc: build,即编译操作,将 src 目录下的 *.ts 文件编译成 *.js 文件;最终,调试器执行的还是 js 文件而非 ts 文件。

问题来了,调试器咋知道你编译后的 js 文件放在那里呢?下面👇属性 outFiles 告诉它的。

outFiles

该属性告诉调试器执行的 js 文件在哪个目录下,上面例子编译后的 js 文件都放在 dist 目录下。

既然调试器执行的是 js 代码,为什么我们可以在 ts 文件中打断点呢?

tsconfig.json 中有个配置项 sourceMap,当设置为 true 时,在 *.ts 文件编译成 *.js 文件时,会顺带生成 *.js.map 文件,这个文件将 *.ts 和 *.js 文件关联起来了,所以可以在 ts 文件打断点。

posted @ 2020-04-16 13:12  杰_森  阅读(864)  评论(0编辑  收藏  举报