diff --git a/packages/compiler-ssr/__tests__/ssrComponent.spec.ts b/packages/compiler-ssr/__tests__/ssrComponent.spec.ts index 2c7f7e307..04ebb890a 100644 --- a/packages/compiler-ssr/__tests__/ssrComponent.spec.ts +++ b/packages/compiler-ssr/__tests__/ssrComponent.spec.ts @@ -57,13 +57,25 @@ describe('ssr: components', () => { ``, ).code, ).toMatchInlineSnapshot(` - "const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps, createVNode: _createVNode } = require("vue") - const { ssrRenderVNode: _ssrRenderVNode } = require("vue/server-renderer") + "const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps, createVNode: _createVNode } = require("vue") + const { ssrRenderVNode: _ssrRenderVNode } = require("vue/server-renderer") - return function ssrRender(_ctx, _push, _parent, _attrs) { - _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent("div"), _mergeProps({ innerHTML: '
ssr dynamic component v-html
' }, _attrs), null), _parent) - }" - `) + return function ssrRender(_ctx, _push, _parent, _attrs) { + _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent("div"), _mergeProps({ innerHTML: '
ssr dynamic component v-html
' }, _attrs), null), _parent) + }" + `) + + expect( + compile(``) + .code, + ).toMatchInlineSnapshot(` + "const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps, createVNode: _createVNode } = require("vue") + const { ssrRenderVNode: _ssrRenderVNode } = require("vue/server-renderer") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent("div"), _mergeProps({ textContent: 'ssr dynamic component v-text' }, _attrs), null), _parent) + }" + `) }) describe('slots', () => { diff --git a/packages/compiler-ssr/src/index.ts b/packages/compiler-ssr/src/index.ts index 2c7ec97e5..d7fb043b9 100644 --- a/packages/compiler-ssr/src/index.ts +++ b/packages/compiler-ssr/src/index.ts @@ -28,6 +28,7 @@ import { ssrTransformShow } from './transforms/ssrVShow' import { ssrInjectFallthroughAttrs } from './transforms/ssrInjectFallthroughAttrs' import { ssrInjectCssVars } from './transforms/ssrInjectCssVars' import { ssrTransformHtml } from './transforms/ssrVHtml' +import { ssrTransformText } from './transforms/ssrVText' export function compile( source: string | RootNode, @@ -73,9 +74,10 @@ export function compile( // reusing core v-bind bind: transformBind, on: transformOn, - // model, show and html have dedicated SSR handling + // model, show, text and html have dedicated SSR handling model: ssrTransformModel, show: ssrTransformShow, + text: ssrTransformText, html: ssrTransformHtml, // the following are ignored during SSR // on: noopDirectiveTransform, diff --git a/packages/compiler-ssr/src/transforms/ssrVText.ts b/packages/compiler-ssr/src/transforms/ssrVText.ts new file mode 100644 index 000000000..81c3ebee7 --- /dev/null +++ b/packages/compiler-ssr/src/transforms/ssrVText.ts @@ -0,0 +1,37 @@ +import { + type DirectiveTransform, + ElementTypes, + TO_DISPLAY_STRING, + createCallExpression, + createObjectProperty, + createSimpleExpression, + getConstantType, +} from '@vue/compiler-core' + +export const ssrTransformText: DirectiveTransform = (dir, node, context) => { + const { exp, loc } = dir + + if (node.tagType !== ElementTypes.COMPONENT || node.tag !== 'component') + return { props: [] } + + if (node.children.length) { + node.children.length = 0 + } + + return { + props: [ + createObjectProperty( + createSimpleExpression(`textContent`, true), + exp + ? getConstantType(exp, context) > 0 + ? exp + : createCallExpression( + context.helperString(TO_DISPLAY_STRING), + [exp], + loc, + ) + : createSimpleExpression('', true), + ), + ], + } +}