From 31b5eeb4c2cadd60224ebeb3efb0b0d359ef7651 Mon Sep 17 00:00:00 2001 From: NoTwoBoy <1244476905@qq.com> Date: Tue, 10 Dec 2024 20:09:25 +0800 Subject: [PATCH 1/2] fix(ssr): handle the dynamicComponent compiling in SSR --- .../__tests__/ssrComponent.spec.ts | 13 ++++++++++ packages/compiler-ssr/src/index.ts | 4 ++- .../compiler-ssr/src/transforms/ssrVHtml.ts | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 packages/compiler-ssr/src/transforms/ssrVHtml.ts diff --git a/packages/compiler-ssr/__tests__/ssrComponent.spec.ts b/packages/compiler-ssr/__tests__/ssrComponent.spec.ts index 2fde4560e..2c7f7e307 100644 --- a/packages/compiler-ssr/__tests__/ssrComponent.spec.ts +++ b/packages/compiler-ssr/__tests__/ssrComponent.spec.ts @@ -51,6 +51,19 @@ describe('ssr: components', () => { _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(_ctx.foo), _mergeProps({ prop: "b" }, _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({ innerHTML: '
ssr dynamic component v-html
' }, _attrs), null), _parent) + }" + `) }) describe('slots', () => { diff --git a/packages/compiler-ssr/src/index.ts b/packages/compiler-ssr/src/index.ts index f8a686555..2c7ec97e5 100644 --- a/packages/compiler-ssr/src/index.ts +++ b/packages/compiler-ssr/src/index.ts @@ -27,6 +27,7 @@ import { ssrTransformModel } from './transforms/ssrVModel' import { ssrTransformShow } from './transforms/ssrVShow' import { ssrInjectFallthroughAttrs } from './transforms/ssrInjectFallthroughAttrs' import { ssrInjectCssVars } from './transforms/ssrInjectCssVars' +import { ssrTransformHtml } from './transforms/ssrVHtml' export function compile( source: string | RootNode, @@ -72,9 +73,10 @@ export function compile( // reusing core v-bind bind: transformBind, on: transformOn, - // model and show have dedicated SSR handling + // model, show and html have dedicated SSR handling model: ssrTransformModel, show: ssrTransformShow, + html: ssrTransformHtml, // the following are ignored during SSR // on: noopDirectiveTransform, cloak: noopDirectiveTransform, diff --git a/packages/compiler-ssr/src/transforms/ssrVHtml.ts b/packages/compiler-ssr/src/transforms/ssrVHtml.ts new file mode 100644 index 000000000..5aa59e0ac --- /dev/null +++ b/packages/compiler-ssr/src/transforms/ssrVHtml.ts @@ -0,0 +1,26 @@ +import { + type DirectiveTransform, + ElementTypes, + createObjectProperty, + createSimpleExpression, +} from '@vue/compiler-core' + +export const ssrTransformHtml: DirectiveTransform = (dir, node) => { + 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(`innerHTML`, true, loc), + exp || createSimpleExpression('', true), + ), + ], + } +} From d6e734e8446e520022fc50e169f89af1412a23e8 Mon Sep 17 00:00:00 2001 From: NoTwoBoy <1244476905@qq.com> Date: Tue, 10 Dec 2024 20:32:15 +0800 Subject: [PATCH 2/2] feat: add ssrVText transform --- .../__tests__/ssrComponent.spec.ts | 24 +++++++++--- packages/compiler-ssr/src/index.ts | 4 +- .../compiler-ssr/src/transforms/ssrVText.ts | 37 +++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 packages/compiler-ssr/src/transforms/ssrVText.ts 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), + ), + ], + } +}