ComfyUI-Subgraph-Preview
I got tired of waiting for ComfyUI to enable Subgraph previews so I made my own patch.
ComfyUI-Subgraph-Preview
<p align="center"> <img src="examples/banner.png" width="400" alt="Live preview is back"> </p>Shows sampler previews on subgraph nodes, so you don't have to open the subgraph to see what's going on.
If you collapse part of your workflow into a subgraph, the preview disappears. The subgraph node just sits there while the sampler runs inside it and you can't see anything until it finishes. This extension draws the preview on the subgraph node itself, and it can also keep the final image there once the run is done.
It's frontend only. No new nodes, no Python dependencies, nothing on the backend.
What it looks like
The sampler is running inside the subgraph, and you can watch it from outside.
<p align="center"> <img src="examples/demo.gif" width="260" alt="Live sampler preview drawn on a subgraph node"> </p>Why it doesn't work by default
The preview data is already there. ComfyUI sends every preview frame to all the
parent execution ids, so app.nodePreviewImages[<host locator>] gets filled
while a sampler inside the subgraph is running. Nothing ever draws it.
Two things get in the way:
- Drawing promoted previews was only implemented for the Vue Nodes renderer, so on the normal canvas you get nothing.
showCanvasImagePreview()gives up on subgraph nodes, becauseSubgraphNode.widgetsis a computed getter and can't hold a preview widget.
So this extension adds the drawing step that's missing on the canvas renderer.
Install
With ComfyUI Manager, search for "Subgraph Preview" and install it.
Or clone it into ComfyUI/custom_nodes/:
git clone https://github.com/marcsole96/ComfyUI-Subgraph-Preview
Then restart ComfyUI and refresh the browser. It loads frontend code, so a hard refresh helps.
Settings
They're under Settings > LiteGraph > Subgraph:
| Setting | Default | What it does | |---|---|---| | Show generation previews on subgraph nodes | on | Draws the live sampler preview on the subgraph node | | Keep the final image on subgraph nodes | on | After the run, keeps showing the output of the deepest interior node that made images | | Max preview height on subgraph nodes | 320 | How tall the preview can get (96 to 1024) |
If you resize a subgraph node by hand, the extension stops managing its height. It only touches a height it set itself.
Compatibility
Built and tested on ComfyUI 0.33.0 with comfyui-frontend-package 1.48.7, on the classic canvas renderer. In Vue Nodes mode it turns itself off, since that renderer already draws these previews.
It hooks into frontend internals rather than a public API, so a big frontend refactor could break it. If that happens, open an issue.
How it works
A few notes in case anyone wants to do something similar:
- It hooks
LGraphCanvas.drawNodeinstead ofLGraphNode.onDrawBackground. Subgraph nodes define their ownonDrawBackground, which shadows anything you put onLGraphNode.prototype, so that hook never runs. Every node passes throughdrawNode, and by then the context is already translated to the node origin, so you get the same coordinatesonDrawBackgroundwould have given. - To pick what to show, it first checks the node's own preview, then walks the interior nodes (up to 8 levels of nesting) for a live preview that the fan-out missed, and finally falls back to the output images of the deepest interior node that produced any.
- The preview is anchored to the node's computed content height, not its
current height.
node.sizegets saved into the workflow and already includes the preview block, so anchoring to that makes the node grow taller every time you save and reload. - Decoded images are cached per node and only rebuilt when the URLs change. Settings are cached for 250ms so the settings store isn't queried for every node on every frame.
- Only the foreground canvas gets invalidated. If you dirty the background too, ComfyUI's own preview widget starts dropping frames, because it defers its drawImage into a microtask.
If something isn't working
Open the browser console and run __sgpDebug(). It says whether the hook is
installed, and then for each subgraph node prints the locator id, whether
there's a live preview, how many URLs it resolved, how many times it drew, how
many images decoded, and the node size. After that it logs every preview frame
that arrives, so you can queue a run and see what comes in.
License
MIT, see LICENSE.