diff --git a/src/index.ts b/src/index.ts
index 890dc1cb3..5648adf50 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -11,6 +11,7 @@ import type {
SFCTemplateCompileOptions,
SFCScriptCompileOptions,
} from 'vue/compiler-sfc'
+
import { selectBlock } from './select'
import { genHotReloadCode } from './hotReload'
import { genCSSModulesCode } from './cssModules'
@@ -363,6 +364,18 @@ export default function loader(
.join(`\n`) + `\n`
}
+ if (isServer) {
+ code += `\nimport { useSSRContext } from 'vue'\n`
+ code += `const _setup = script.setup\n`
+ ;(code += `script.setup = (props, ctx) => {`),
+ (code += ` const ssrContext = useSSRContext()`),
+ (code += ` ;(ssrContext._registeredComponents || (ssrContext._registeredComponents = new Set())).add(${JSON.stringify(
+ hash(loaderContext.request)
+ )});`)
+ code += ` return _setup ? _setup(props, ctx) : undefined`
+ code += `}\n`
+ }
+
// finalize
if (!propsToAttach.length) {
code += `\n\nconst __exports__ = script;`
diff --git a/test/fixtures/functional-style.vue b/test/fixtures/functional-style.vue
new file mode 100644
index 000000000..a625668b8
--- /dev/null
+++ b/test/fixtures/functional-style.vue
@@ -0,0 +1,13 @@
+
+
+
diff --git a/test/fixtures/ssr-entry.js b/test/fixtures/ssr-entry.js
new file mode 100644
index 000000000..19ea19c93
--- /dev/null
+++ b/test/fixtures/ssr-entry.js
@@ -0,0 +1,17 @@
+import { renderToString } from 'vue/server-renderer'
+import { createSSRApp } from 'vue'
+
+import Component from '~target'
+import * as exports from '~target'
+
+export async function main() {
+ const instance = createSSRApp(Component)
+ const ssrContext = {}
+ const markup = await renderToString(instance, ssrContext)
+ return {
+ instance,
+ markup,
+ componentModule: Component,
+ ssrContext,
+ }
+}
diff --git a/test/fixtures/ssr-style.vue b/test/fixtures/ssr-style.vue
new file mode 100644
index 000000000..55d15f674
--- /dev/null
+++ b/test/fixtures/ssr-style.vue
@@ -0,0 +1,25 @@
+
+
+
Hello
+
+
+
+
+
+
+
+
+
+
diff --git a/test/ssr.spec.ts b/test/ssr.spec.ts
new file mode 100644
index 000000000..a21f9afab
--- /dev/null
+++ b/test/ssr.spec.ts
@@ -0,0 +1,79 @@
+import { mockServerBundleAndRun, genId, DEFAULT_VUE_USE } from './utils'
+
+test('SSR style and moduleId extraction', async () => {
+ const { markup, ssrContext } = await mockServerBundleAndRun({
+ entry: 'ssr-style.vue',
+ })
+
+ expect(markup).toContain('Hello
')
+ expect(markup).toContain('Hello from Component A!')
+ expect(markup).toContain('functional
')
+ // collect component identifiers during render
+ expect(Array.from(ssrContext._registeredComponents).length).toBe(3)
+})
+
+test('SSR with scoped CSS', async () => {
+ const { markup } = await mockServerBundleAndRun({
+ entry: 'scoped-css.vue',
+ })
+
+ const shortId = genId('scoped-css.vue')
+ const id = `data-v-${shortId}`
+
+ expect(markup).toContain(``)
+ expect(markup).toContain(`