On this page
调试
Deno 支持 V8 检查器协议,这是 Chrome、Edge 和 Node.js 使用的协议。这使得可以使用 Chrome DevTools 或其他支持该协议的客户端(例如 VSCode)调试 Deno 程序。
要激活调试功能,请使用以下标志之一运行 Deno:
--inspect--inspect-wait--inspect-brk
--inspect Jump to heading
使用 --inspect 标志将启动一个带有 inspector 服务器的程序,这样就可以从支持 V8 Inspector 协议的工具(例如 Chrome DevTools)连接客户端。
在 Chromium 兼容的浏览器中访问 chrome://inspect 以将 Deno 连接到 inspector 服务器。这允许您检查代码、添加断点并逐步执行代码。
deno run --inspect your_script.ts
您可以选择为 inspector 服务器指定主机和端口。完整地址和纯端口号都可以接受:
# 默认:监听 127.0.0.1:9229
deno run --inspect your_script.ts
# 自定义端口
deno run --inspect=9230 your_script.ts
# 自定义主机和端口
deno run --inspect=0.0.0.0:9229 your_script.ts
--inspect-publish-uid Jump to heading
默认情况下,Deno 在开始监听时会将 inspector WebSocket URL 打印到 stderr。您可以使用 --inspect-publish-uid 来控制这一行为:
stderr(默认)— 在启动时将 URL 打印到 stderrhttp— 通过 inspector 端口上的/json/listHTTP 端点公开该 URL,而不是打印它;这对以编程方式轮询可用目标的工具很有用
deno run --inspect --inspect-publish-uid=http your_script.ts
如果您使用 --inspect 标志,代码将立即开始执行。如果您的程序较短,您可能没有足够的时间在程序完成执行之前连接调试器。
在这种情况下,请尝试使用 --inspect-wait 或 --inspect-brk 标志,或者在代码的结尾添加一个超时。
--inspect-wait Jump to heading
--inspect-wait 标志将在执行代码之前等待调试器连接。
deno run --inspect-wait your_script.ts
--inspect-brk Jump to heading
--inspect-brk 标志将在执行代码之前等待调试器连接,然后在您连接后立即在您的程序中设置一个断点,允许您在继续执行之前添加额外的断点或评估表达式。
这是最常用的 inspect 标志。JetBrains 和 VSCode IDE 默认使用此标志。
deno run --inspect-brk your_script.ts
运行时激活检查器 Jump to heading
--inspect 标志会在进程启动时启动检查器服务器。如果你希望在已经运行的程序中按需打开检查器,则可以在程序内部使用
node:inspector 模块,或者从程序外部向进程发送
SIGUSR1 信号。这对于服务器等长时间运行的进程非常有用:你可能只希望在满足某个条件后让调试器开始监听,而不是让它在整个进程生命周期内都处于监听状态。
inspector.open([port][, host][, wait]) 会启动检查器服务器。端口默认是 9229,主机默认是 127.0.0.1。由于它会绑定网络套接字,程序需要 --allow-net 权限(或者使用 -A 运行)。
import inspector from "node:inspector";
Deno.serve((req) => {
if (new URL(req.url).pathname === "/debug" && !inspector.url()) {
inspector.open(9229, "127.0.0.1");
console.log("Inspector listening on", inspector.url());
}
return new Response("hello");
});
deno run --allow-net server.ts
向 /debug 发送请求后,检查器服务器就会启动;在基于 Chromium 的浏览器中打开
chrome://inspect 即可连接。该模块还提供了一些相关函数:
inspector.open(port, host, true)— 将第三个参数传入true会阻塞,直到客户端连接;这与inspector.waitForDebugger()的效果相同。inspector.url()— 返回检查器的 WebSocket URL;如果检查器未激活,则返回undefined。inspector.close()— 停止检查器服务器。
还提供了一个 Session,可用于以编程方式发出
Chrome DevTools Protocol
命令,而无需外部客户端。
将检查器绑定到开放端口的公共 IP 上是不安全的:任何能够访问该端口的主机都可以连接到检查器并执行任意代码。除非你完全控制网络,否则请将 host 保持为 127.0.0.1。
使用信号启动检查器 Jump to heading
从 Deno 2.9.2 开始,在 Linux 和 macOS 上,你还可以通过向进程发送 SIGUSR1 信号,从进程外部激活检查器,其工作方式与 Node.js 中相同。检查器服务器会在默认地址 127.0.0.1:9229 上启动,不会暂停执行,并将常规提示信息输出到 stderr:
$ deno run server.ts &
$ kill -USR1 <pid>
Debugger listening on ws://127.0.0.1:9229/ws/...
Visit chrome://inspect to connect to the debugger.
这对于调试长时间运行的进程(例如服务器)很有用,尤其是该进程在启动时未使用 --inspect 标志,且无法轻易重启时。与 inspector.open() 不同,它不需要任何权限,也不需要程序代码的配合。
以下是一些需要注意的细节:
- 如果检查器服务器已经在运行(通过
--inspect*标志、inspector.open()或之前的SIGUSR1启动),则该信号不会产生任何效果。 - 信号处理程序会在启动后不久安装,因此此功能适用于运行时间超过约半秒的程序。
- 使用
Deno.addSignalListener("SIGUSR1")添加的信号监听器会与此处理程序同时正常工作。 - Windows 上不存在
SIGUSR1,因此无法使用此功能。
使用 Chrome DevTools 的示例 Jump to heading
让我们尝试使用 Chrome DevTools 调试一个程序。为此,我们将使用
@std/http/file-server,一个静态文件服务器。
使用 --inspect-brk 标志在第一行中暂停执行:
$ deno run --inspect-brk -RN jsr:@std/http/file-server
Debugger listening on ws://127.0.0.1:9229/ws/1e82c406-85a9-44ab-86b6-7341583480b1
...
在像 Google Chrome 或 Microsoft Edge 这样的 Chromium 兼容浏览器中,打开 chrome://inspect 并点击目标旁边的“检查”:

打开 DevTools 后可能需要几秒钟才能加载所有模块。

您可能会注意到 DevTools 在 _constants.ts 的第一行暂停执行,而不是在 file_server.ts。这是由于 JavaScript 中 ES 模块的评估方式造成的预期行为(_constants.ts 是 file_server.ts 的最左侧、最底部依赖项,因此它首先被评估)。
此时,所有源代码在 DevTools 中均可用,所以让我们打开 file_server.ts 并在此添加断点;转到“源代码”面板并展开树形结构:

仔细查看您会发现每个文件都有重复条目;一个是常规写法,一个是斜体。前者是编译的源文件(因此在 .ts 文件的情况下,它将发出 JavaScript 源),而后者是该文件的源映射。
接下来,在 listenAndServe 方法中添加一个断点:

一旦添加了断点,DevTools 将自动打开源映射文件,这让我们可以逐步查看包含类型的实际源代码。
现在我们已经设置了断点,可以继续执行脚本,以便检查传入的请求。点击“恢复脚本执行”按钮来完成。您可能需要点击两次!
一旦我们的脚本在运行,尝试发送请求并在 DevTools 中检查它:
curl http://0.0.0.0:4507/

此时我们可以检查请求的内容,并逐步调试代码。
检查网络流量 Jump to heading
从 Deno 2.8 开始,Chrome DevTools 可以像检查浏览器标签页中的流量一样检查您的程序发出的网络流量。使用 --inspect-wait(或 --inspect / --inspect-brk)运行程序,在 Chromium 衍生浏览器中打开 chrome://inspect,点击 Deno 目标上的 Inspect,然后切换到 Network 选项卡。
以下内置 API 已接入 Network 选项卡:
fetch()— 请求会以Type: fetch显示node:http和node:https客户端请求(http.request、http.get、https.request、https.get)— Type 列会反映响应内容类型(例如json、document),因此任何通过node:http发出 HTTP 请求的 npm 库也会与fetch()流量一起显示WebSocket— 客户端连接会与 HTTP 请求一起显示,并带有握手状态和升级响应中的头信息、消息帧,以及套接字关闭时的关闭事件Deno.upgradeWebSocket()— 服务端 WebSocket 升级也会被记录,因此您可以从 Deno 到 Deno 的握手中检查连接双方
对于每个请求,您都可以查看 URL、方法、状态码、请求和响应头、请求和响应正文,以及耗时信息。
让我们用一个使用 fetch() 的小程序来试试:
const res = await fetch("https://api.github.com/repos/denoland/deno");
console.log(res.status, (await res.json()).stargazers_count);
使用 --inspect-wait 运行它,这样程序会暂停直到 DevTools 连接:
$ deno run --inspect-wait --allow-net net.ts
Debugger listening on ws://127.0.0.1:9229/...
Visit chrome://inspect to connect to the debugger.
Deno is waiting for debugger to connect.
打开 chrome://inspect,在 Deno 目标上点击 Inspect,然后切换到 Network 选项卡。fetch() 请求会作为常规网络条目显示,并且请求和响应面板会填充内容:

点击某个请求可以查看其头信息、负载、响应正文和耗时分布:

node:http 和 node:https 也同样适用,因此通过 Node 内置客户端(而不是 fetch())发出 HTTP 请求的 npm 库也会显示在 Network 选项卡中。例如:
import https from "node:https";
const options = {
hostname: "api.github.com",
path: "/repos/denoland/deno",
headers: { "User-Agent": "deno-docs-example" },
};
https.get(options, (res) => {
let body = "";
res.on("data", (chunk) => body += chunk);
res.on(
"end",
() => console.log(res.statusCode, JSON.parse(body).stargazers_count),
);
});
$ deno run --inspect-wait --allow-net node-http.ts
该请求会像 fetch() 请求一样在 Network 选项卡中显示相同的头信息、正文和耗时信息——Type 列会反映响应内容类型(此示例中为 json):

WebSocket 连接也会出现在同一个 Network 选项卡中,并随着连接进展显示消息和关闭事件:

使用 Deno.upgradeWebSocket() 创建的服务端 WebSocket 也会被记录,因此您可以检查连接的双方——发出的客户端 WebSocket 和接受它的服务端升级。例如,一个小型回显服务器:
Deno.serve({ port: 8000 }, (req) => {
if (req.headers.get("upgrade") !== "websocket") {
return new Response("发送一个 WebSocket 请求", { status: 426 });
}
const { socket, response } = Deno.upgradeWebSocket(req);
socket.onmessage = (e) => socket.send(`echo: ${e.data}`);
return response;
});
$ deno run --inspect-wait --allow-net ws-server.ts
连接 DevTools 并继续执行后,从另一个终端连接到服务器(例如使用 deno eval):
deno eval 'const ws = new WebSocket("ws://localhost:8000");
ws.onopen = () => ws.send("hello");
ws.onmessage = (e) => { console.log(e.data); ws.close(); };'
升级和消息帧会显示在服务器 DevTools 会话的 Network 选项卡中:

这些相同的事件也通过 node:inspector 暴露给程序化客户端,因此已经针对 Node 使用 Chrome DevTools Protocol 的工具可以连接到 Deno,并在不做任何更改的情况下观察相同的网络流量。
当没有调试器连接时,网络监控实际上没有任何开销——这些事件仅在会话通过 Network.enable 显式启用后才会发出。
VSCode Jump to heading
可以使用 VSCode 调试 Deno。最好的方法是借助官方的 vscode_deno 扩展。有关此扩展的文档可以在 这里 找到。
JetBrains IDE Jump to heading
注意:确保您已安装并在首选项/设置 | 插件中启用 此 Deno 插件。有关更多信息,请参见 此博客文章。
您可以通过右键单击要调试的文件并选择 Debug 'Deno: <file name>' 选项来使用 JetBrains IDE 调试 Deno。

这将创建一个没有权限标志的运行/调试配置。如果您想配置它们,请打开您的运行/调试配置并将所需标志添加到 Command 字段。
--log-level=debug Jump to heading
如果您在连接检查器时遇到问题,可以使用 --log-level=debug 标志,以获取有关发生情况的更多信息。这将显示模块解析、网络请求和其他权限检查等信息。
deno run --inspect-brk --log-level=debug your_script.ts
--strace-ops Jump to heading
Deno ops 是一种 RPC 机制,用于在 JavaScript 和 Rust 之间提供文件 I/O、网络和定时器等功能。--strace-ops 标志将在程序运行时打印所有正在执行的 Deno ops 及其时序。
deno run --strace-ops your_script.ts
每个 op 都应包含一个 Dispatch 和一个 Complete 事件。这两个事件之间的时间即为执行该 op 所花费的时间。此标志对于性能分析、调试挂起的程序或了解 Deno 的底层工作原理非常有用。
CPU 性能分析 Jump to heading
Deno 内置了 CPU 分析器:在程序运行时收集 profile,然后将其作为 Markdown 报告、交互式 flamegraph 或在 Chrome DevTools 中读取。有关标志、报告格式和分析提示,请参见 CPU profiling。
OpenTelemetry 集成 Jump to heading
对于生产应用或复杂系统,OpenTelemetry 提供了更全面的可观测性和调试解决方案。Deno 内置了 OpenTelemetry 支持,允许你:
- 跟踪应用中的请求
- 监控应用性能指标
- 收集结构化日志
- 将遥测数据导出到监控系统
OTEL_DENO=true deno run your_script.ts
这将自动收集并导出运行时可观测性数据,包括:
- HTTP 请求跟踪
- 运行时指标
- 控制台日志和错误
有关 Deno OpenTelemetry 集成的完整详细信息,包括自定义指标、跟踪和配置选项,请参阅 OpenTelemetry 文档。
调试 Web Workers Jump to heading
从 Deno 2.7 开始,可以通过 Chrome DevTools 和 VS Code 调试 Web Workers。运行程序时使用任何 --inspect 标志,每个创建的 worker 都会与主线程一起作为单独的目标显示在 chrome://inspect 中。
const worker = new Worker(import.meta.resolve("./worker.ts"), {
type: "module",
});
worker.postMessage("start");
self.onmessage = (e) => {
console.log("Worker received:", e.data);
// 在 DevTools 中于此处设置断点
};
deno run --inspect-brk --allow-read main.ts
打开 chrome://inspect,您会看到 main.ts 和 worker.ts 都作为可单独检查的目标列出。点击 worker 目标上的 Inspect,即可为该 worker 打开一个专用的 DevTools 面板,您可以在其中设置断点、逐步执行代码,并独立于主线程检查变量。
在安装了 Deno 扩展的 VS Code 中,worker 会作为调试器 Call Stack 面板中的单独线程显示。
TLS 会话调试 Jump to heading
设置 SSLKEYLOGFILE 环境变量以将 TLS 会话密钥记录到文件中。
这使您可以使用 Wireshark 等工具解密并检查加密网络流量:
SSLKEYLOGFILE=./keys.log deno run -N main.ts
然后在 Wireshark 中加载 keys.log(编辑 > 首选项 > 协议 > TLS >
(Pre)-Master-Secret log filename)以解密捕获的 TLS 流量。
Last updated on