Skip to content

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 to console.{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 module virtual:mt-debug/ssr. It writes ANSI-colored output directly to process.stdout. As a fallback for SSR setups that run in the same process, the plugin also installs $debug on the Vite dev server's globalThis from configureServer.

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:

ts
// 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.config restart 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:

text
[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.