Reveal 连接方式选型指南:repl、prepl 与 remote-prepl 三种模式一次看懂
【免费下载链接】revealRead Eval Visualize Loop for Clojure项目地址: https://gitcode.com/gh_mirrors/rev/reveal
如果你正在学习 Clojure 可视化调试工具,那么Reveal(Read Eval Visualize Loop)的三种连接方式是你绕不开的选型问题:repl(进程内 REPL)、prepl(进程内标准输入输出连接)和remote-prepl(远程网络客户端连接)。Reveal 是一个运行在 JVM 进程内的可视化 REPL 窗口,它能让你在图形界面里直接检查、点击并操作运行中程序里的真实对象,而不仅仅是看一行行文本。
GIF 演示:Reveal REPL 窗口展示 Clojure 程序的运行结果,选中值即可在可视化面板中检查
一分钟理解:三种连接方式解决什么问题?
传统 REPL 的输出是"死的"文本,而 Reveal 的输出面板里每个值都保留了对 VM 中真实对象的引用——选中一段输出、右键,就能打开上下文菜单做可视化检查。
但要让 Reveal 窗口和你的程序"通信",有三种通道,本质区别只有一条:
Reveal 窗口和程序跑在同一个 JVM 里(进程内),还是通过网络连接(进程间)?
方式一:repl—— 进程内 REPL,功能最完整
这是 Reveal 的招牌模式。它包装了clojure.main/repl,在同一个进程里启动一个图形化 REPL 窗口,输入、求值、tap、异常都会流进窗口并保留对象引用。
- 入口函数:vlaaad/reveal.clj 中的
repl - 核心实现:vlaaad/reveal/repl.clj
典型用法:在deps.edn里加一个 alias,然后一条命令启动:
:repl {:main-opts ["-m" "vlaaad.reveal" "repl"]}clj -M:repl特点:
- ✅ 完全进程内,可直接访问 VM 中的全部对象
- ✅ 支持
:infer-ns(从^{:eval-file ...}元数据自动推断命名空间) - ✅ 支持窗口选项:
:always-on-top、:close-difficulty、:title等 - 求值
:repl/quit即可退出
适用场景:开发期在本地调试自己的服务,想要"所见即所得"地检查 atom、ref、future 等任意值。
方式二:prepl(io-prepl)—— 进程内但走标准输入输出
io-prepl基于clojure.core.server/prepl,绑定程序的*in*/*out*,同样运行在目标进程内,但所有交互通过标准输入输出进行。这个模式的杀手锏是:IDE 和编辑器可以充当"输入端"。
- 入口函数:vlaaad/reveal.clj 中的
io-prepl - 核心实现:vlaaad/reveal/prepl.clj
典型用法:
:prepl {:main-opts ["-m" "vlaaad.reveal" "io-prepl"]}clj -M:prepl特点:
- ✅ 对象检查能力与
repl相同(同进程) - ✅ 可用
:valf定制值的序列化方式(默认pr-str) - ✅ 适合嵌入到自己的启动脚本,配合外部编辑器(如 Emacs CIDER 风格的输入流)
适用场景:你的程序已经有自己的入口点(比如先起了 HTTP 服务再进 REPL),想在不打断启动流程的前提下接入 Reveal 窗口。
方式三:remote-prepl—— 远程客户端,跨 JVM 与 ClojureScript
前两种方式都要求Reveal 运行在目标进程的 classpath 里。但有些场景做不到:远程服务器上跑的生产 JVM 没法加依赖,或者你要连的是ClojureScript 的 prepl。这时就用remote-prepl:它在本地启动 Reveal 窗口,通过网络 socket 连接远端端口。
- 入口函数:vlaaad/reveal.clj 中的
remote-prepl - 核心实现:vlaaad/reveal/prepl.clj 中的
remote-prepl
典型用法:
;; 连接本机 5555 端口 (remote-prepl :port 5555) ;; 跨网络连接到远程机器 (remote-prepl :host "192.168.1.15" :port 5555)远端只需一行代码起服务(deps.edn中官方示例 alias):
:server {:exec-fn clojure.core.server/start-server :exec-args {:port 5555 :accept vlaaad.reveal/repl :server-daemon false}}特点:
- ✅ 远端 JVM不需要classpath 上有 Reveal
- ✅ 可连接ClojureScript prepl
- ⚠️ 只能检查通过网络序列化回来的数据(默认用 EDN tagged-literal 反序列化,可用
:valf identity关闭反序列化)
适用场景:调试远程/生产环境的 JVM、CLJS 开发、容器内无法改 classpath 的服务。
三种连接方式对比速查表
| 维度 | repl | prepl(io-prepl) | remote-prepl |
|---|---|---|---|
| 运行位置 | 进程内 | 进程内 | 本地窗口 + 远端网络 |
| 远端需 Reveal 依赖 | 是 | 是 | 否 |
| 检查真实对象 | ✅ 完整 | ✅ 完整 | ⚠️ 仅序列化数据 |
| 通信通道 | 进程内直接调用 | *in*/*out*标准流 | TCP socket(host/port) |
| 可连 ClojureScript | ❌ | ❌ | ✅ |
| 官方 alias | :repl | :prepl | 客户端remote-prepl |
选型指南:3 个问题帮你确定用哪种
问题 1:Reveal 能放进目标程序的 classpath 吗?
- 能 → 优先进程内(
repl或prepl),检查能力最强 - 不能(生产 JVM / 容器 / CLJS)→
remote-prepl
问题 2:程序有自定义启动流程吗?
- 没有,纯开发调试 →
repl,最简单直接 - 有(先起服务再交互)→
io-prepl,绑定标准输入输出不打断启动
问题 3:需要跨机器 / 跨语言(CLJS)连接吗?
- 需要 →
remote-prepl是唯一选择
一句话总结:本地开发默认用repl;嵌进应用启动流程用prepl;够不着 classpath 时上remote-prepl。
附赠:nrepl 中间件 —— 让 IDE 也能"看见" Reveal
如果你习惯在 IDE(CIDER、Cursive 等)里开发,vlaaad/reveal/nrepl.clj 提供了一个 nrepl 中间件,把 IDE 发来的 eval 请求的响应同步流进 Reveal 窗口:
:nrepl {:extra-deps {nrepl/nrepl {:mvn/version "0.6.0"}} :main-opts ["-m" "nrepl.cmdline" "--middleware" "[vlaaad.reveal.nrepl/middleware]"]}它本质上是给 nrepl 的 transport 包了一层:show-output拦截每条 nrepl 消息,把 value/out/err 用 Reveal 的流式系统渲染进窗口。这样 IDE 照常工作,Reveal 窗口同步展示可交互的结果。
写在最后
- 三种方式的核心差异是进程内 vs 网络:进程内拿到的是对象引用,网络拿到的是序列化数据
- 所有启动入口都集中在 vlaaad/reveal.clj,窗口行为由
ui统一驱动(vlaaad/reveal/ui.clj) - 官方依赖声明与 alias 见 deps.edn,9 个可运行示例见 examples/ 目录(如 e02_integrant_live_system_view.clj 演示了如何把 Reveal 贴到运行中的服务上做实时监控)
选对连接方式,Reveal 的可视化检查能力才能真正发挥出来——从"读文本"升级为"操作对象"。
【免费下载链接】revealRead Eval Visualize Loop for Clojure项目地址: https://gitcode.com/gh_mirrors/rev/reveal
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考