Server-side rendering (SSR)
$debug is available inside server-rendered code: route guards, store reducers, page setup, server middleware. The plugin installs the global on both sides.
Browser and server runtimes
- Browser: the runtime is injected via
transformIndexHtml. It logs toconsole.{error|warn|info|debug|log|trace}and forwards each call over the Vite WebSocket to the dev terminal. - Server: a Node runtime is injected automatically into every SSR-transformed module that references
$debug, through the virtual modulevirtual:mt-debug/ssr. It writes ANSI-colored output directly toprocess.stdout. As a fallback for SSR setups that run in the same process, the plugin also installs$debugon the Vite dev server'sglobalThisfromconfigureServer.
The Vite process and server-rendered code run the same runtime, so a call prints the same way from an SSR module, from vite.config.ts or from another plugin. output.terminal: false silences server-side output too, and $debug stays defined.
In production builds (vite build, including SSR builds), every call site is stripped to void 0, on either side. No SSR runtime ships in the output: see Production builds.
Manual SSR opt-in
For SSR runners in a worker thread or a separate process, which do not share globalThis with Vite, import the virtual module from your server entry:
// e.g. src/main.server.ts (Analog) or a Nuxt server plugin
import "virtual:mt-debug/ssr";The module is safe to import more than once: it installs $debug when the global is absent, replaces an earlier instance of its own runtime (for example after a Vite config restart), and never overwrites a $debug your app defined. It only loads in development: the production strip removes any reference to it. It is served to the SSR pipeline only: imported from client code, it is an empty module. With string redact entries configured, a runner in a process of its own prints nothing: see String redact entries on the server.
Server-side calls also reach the NDJSON log file when the SSR runtime executes inside the Vite process; a separate SSR worker is not seen. See NDJSON log file.
String redact entries on the server
A string redact entry, usually a secret read from the environment, is never written into the SSR runtime: each print reads it from the memory of the process that loads your config. It reaches:
- SSR inside the Vite process:
ssrLoadModule, the module runner,vite-node; - a worker thread started after the plugin, such as Nuxt's Nitro worker, after a
nuxt.configrestart too.
SSR in a process of its own, or in workerd (@cloudflare/vite-plugin), cannot read it. There $debug prints nothing rather than print a line with your string entries unmasked, and warns once:
[MARS-TECH] $debug prints nothing in this process: the string entries of your redact option do not reach it, and it does not print what it cannot mask. […]To see output there, describe each such value with a RegExp for its shape (/sk_live_[A-Za-z0-9]+/) instead of a string. A worker thread started before the plugin was constructed is in the same situation: restart it. Without string entries, every runtime prints, masked by your RegExp entries and redactDefaults. See Where string entries cannot reach.