Skip to content

feat: show SSR output #343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 13, 2025
Merged

feat: show SSR output #343

merged 1 commit into from
Jun 13, 2025

Conversation

skirtles-code
Copy link
Contributor

@skirtles-code skirtles-code commented Jun 10, 2025

This adds an option to show the SSR output.

My goal was to make it a bit easier to investigate SSR hydration problems by showing the generated HTML directly in the UI.

The new option is disabled by default, but it is enabled in test/main.ts.

I've also exposed the SSR context object, which is populated if teleports or sync watchers are used.

SSR Output

Copy link

vercel bot commented Jun 10, 2025

@skirtles-code is attempting to deploy a commit to the vuejs Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

pkg-pr-new bot commented Jun 10, 2025

Open in StackBlitz

npm i https://pkg.pr.new/@vue/repl@343

commit: a875b42

Comment on lines +32 to +39
get: () => store.value.outputMode,
set: (value) => (store.value.outputMode = value),
})

watchEffect(() => {
if (!modes.value.includes(mode.value)) {
mode.value = modes.value[0]
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched to using watchEffect because I wanted the value in the store to be updated if the current tab isn't valid. This can happen if SSR mode is turned off when the SSR OUTPUT tab is active. Turning SSR mode back on should stay on the newly active tab, rather than jumping back to SSR OUTPUT.

Comment on lines +244 to +263
const safeContext = {}
const isSafe = (v) =>
v === null ||
typeof v === 'boolean' ||
typeof v === 'string' ||
Number.isFinite(v)
const toSafe = (v) => (isSafe(v) ? v : '[' + typeof v + ']')
for (const prop in rawContext) {
const value = rawContext[prop]
safeContext[prop] = isSafe(value)
? value
: Array.isArray(value)
? value.map(toSafe)
: typeof value === 'object'
? Object.fromEntries(
Object.entries(value).map(([k, v]) => [k, toSafe(v)]),
)
: toSafe(value)
}
return { ssrHtml: html, ssrContext: safeContext }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this looks like a lot, it's just trying to make the SSR context object safe to pass to postMessage without losing too much information.

.ssr-output {
background: var(--bg);
box-sizing: border-box;
color: var(--text-light);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In light mode the text is a bit lighter than I would like, but there didn't seem to be any other variables available I could use and I was reluctant to introduce a new one.

Comment on lines +69 to +73
if (window.__ssr_promise__) {
send_ok(await window.__ssr_promise__)
} else {
send_ok()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a hack, reusing __ssr_promise__ as a way to get the response value. I couldn't see a better alternative. I could have renamed the promise to something more generic, so it wasn't explicitly tied to SSR, but I figured that could be changed later if other use cases like this arise.

@edison1105 edison1105 requested a review from wangcch June 11, 2025 00:08
@edison1105
Copy link
Member

LGTM

@edison1105 edison1105 merged commit 52a193a into vuejs:main Jun 13, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants