feat: forward browser console logs and errors to dev server terminal#20916
Conversation
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
@vitejs/plugin-legacy
vite
commit: |
|
I realized this feature has never had a proper context. This has been raised internally in voidzero as a part of AI coding improvement and I've picked up after #20487. I'll create a proper feature request to accompany with this, but the code here is self-contained and ready for review. |
|
Some thoughts:
|
Yeah or even 'forwardBrowserLogs/Console'? Would it ever not come from a browser? I think just 'error' to start would be good! Log/info could get pretty noisy - could include but default off if it's worth including? |
|
I recommend against using |
|
Thanks for the feedback! We've discussed in the meeting and I updated the description to note some tweaks which I'll do later.
My intent of "runtime" is that to contrast from Vite "plugin" side code (i.e. main Vite node process). Here "runtime" means each Vite environment including ssr and others and we could catch unhandled errors and patch console to do the same thing on ssr, which might run separately from main node process. However, the log and any errors there are usually already visible in the same console for known server environment. We'll adjust option structure and default behavior to take this into account. Also emphasizing the option as
I think we can do this with the options to selectively pick some log levels, something like https://github.com/mitsuhiko/vite-console-forward-plugin?tab=readme-ov-file#usage |
|
📝 Ran ecosystem CI on
✅ marko, ladle, unocss, sveltekit, vite-plugin-svelte, quasar, tanstack-start, vuepress, vite-plugin-react, vite-plugin-cloudflare, vitepress, vite-environment-examples, vite-setup-catalogue, vitest, vite-plugin-vue, waku, vite-plugin-rsc |
|
I experimented with enabling |
| expect( | ||
| serverLogs.slice(lastServerLogIndex).map(stripVTControlCharacters), | ||
| ).toContain('hmr update /self-accept-within-circular/c.js') |
There was a problem hiding this comment.
This was the only one failing when enabling forwardConsole by default on Vite. I adjusted it to make it more robust.
bluwy
left a comment
There was a problem hiding this comment.
Personally I'm conflicted if we should detect agents and enable by default, but not enough that I'd block the PR, just unfortunate that it has a huge license file.
Otherwise I think this is a nice feature to have and indeed we can consider enabling by default in the future.
| if (stack === nearest) { | ||
| const code = fs.readFileSync(stack.file, 'utf-8') | ||
| output += generateCodeFrame(code, stack).replace(/^/gm, ' ') | ||
| output += '\n' | ||
| } |
There was a problem hiding this comment.
TOCTOU (Time-of-Check-Time-of-Use) race condition: The file existence is checked in the find() predicate (line 116), but the file is read later without error handling. The file could be deleted between the check and read, causing an unhandled exception.
if (stack === nearest) {
try {
const code = fs.readFileSync(stack.file, 'utf-8')
output += generateCodeFrame(code, stack).replace(/^/gm, ' ')
output += '\n'
} catch {
// Skip code frame if file is no longer accessible
}
}This will crash the error formatting when files are modified/deleted during development.
| if (stack === nearest) { | |
| const code = fs.readFileSync(stack.file, 'utf-8') | |
| output += generateCodeFrame(code, stack).replace(/^/gm, ' ') | |
| output += '\n' | |
| } | |
| if (stack === nearest) { | |
| try { | |
| const code = fs.readFileSync(stack.file, 'utf-8') | |
| output += generateCodeFrame(code, stack).replace(/^/gm, ' ') | |
| output += '\n' | |
| } catch { | |
| // Skip code frame if file is no longer accessible | |
| } | |
| } |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
Description
This PR adds a browser-to-server console forwarding feature for dev server, so runtime client signals can be surfaced directly in terminal output. This is useful for development with coding agent as the server side log can be easier to be read. For example, when running playwright e2e with Vite dev server in
webServerconfig, playwright pipes stderr by default and it allows agent invoking playwright cli to see through browser side runtime errors and logs directly.Configuration
The basic shape of configuration is a following:
The default becomes true when
@vercel/detect-agentdetect it's running under coding agent. Otherwise it's false.Implementation
The implementation of forwarding and formatting are heavily based on Vitest since the need is basically same. The error stack formatting uses
parseErrorStacktraceutility provided by@vitest/utils. Forconsoleformatting though, as it depends on external dependencyloupeor@vitest/pretty-format, I didn't use the one from@vitest/utilsand instead, copied the similar logic directly to Vite but without sophisticated object formatting.
Comparison with other tools
There are plugins providing similar features, but they didn't seem to have proper stack trace mapping nor console argument formatting.
vite-plugin-mcpis in this repo)Many bundles have similar features as builtin. Most off them enable it by default, but Next.js seems to have this as op-in still (it could be just due to their test infra harder to adopt). You can find examples in:
Follow-up discussion if needed
Example