@vue/compiler-ssr 3.2.29 → 3.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler-ssr.cjs.js +264 -231
- package/package.json +3 -3
package/dist/compiler-ssr.cjs.js
CHANGED
|
@@ -22,6 +22,7 @@ const SSR_RENDER_DYNAMIC_MODEL = Symbol(`ssrRenderDynamicModel`);
|
|
|
22
22
|
const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`ssrGetDynamicModelProps`);
|
|
23
23
|
const SSR_RENDER_TELEPORT = Symbol(`ssrRenderTeleport`);
|
|
24
24
|
const SSR_RENDER_SUSPENSE = Symbol(`ssrRenderSuspense`);
|
|
25
|
+
const SSR_GET_DIRECTIVE_PROPS = Symbol(`ssrGetDirectiveProps`);
|
|
25
26
|
const ssrHelpers = {
|
|
26
27
|
[SSR_INTERPOLATE]: `ssrInterpolate`,
|
|
27
28
|
[SSR_RENDER_VNODE]: `ssrRenderVNode`,
|
|
@@ -39,7 +40,8 @@ const ssrHelpers = {
|
|
|
39
40
|
[SSR_RENDER_DYNAMIC_MODEL]: `ssrRenderDynamicModel`,
|
|
40
41
|
[SSR_GET_DYNAMIC_MODEL_PROPS]: `ssrGetDynamicModelProps`,
|
|
41
42
|
[SSR_RENDER_TELEPORT]: `ssrRenderTeleport`,
|
|
42
|
-
[SSR_RENDER_SUSPENSE]: `ssrRenderSuspense
|
|
43
|
+
[SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`,
|
|
44
|
+
[SSR_GET_DIRECTIVE_PROPS]: `ssrGetDirectiveProps`
|
|
43
45
|
};
|
|
44
46
|
// Note: these are helpers imported from @vue/server-renderer
|
|
45
47
|
// make sure the names match!
|
|
@@ -265,224 +267,6 @@ function ssrProcessTransitionGroup(node, context) {
|
|
|
265
267
|
}
|
|
266
268
|
}
|
|
267
269
|
|
|
268
|
-
// We need to construct the slot functions in the 1st pass to ensure proper
|
|
269
|
-
// scope tracking, but the children of each slot cannot be processed until
|
|
270
|
-
// the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
|
|
271
|
-
// pass and complete them in the 2nd pass.
|
|
272
|
-
const wipMap$1 = new WeakMap();
|
|
273
|
-
const componentTypeMap = new WeakMap();
|
|
274
|
-
// ssr component transform is done in two phases:
|
|
275
|
-
// In phase 1. we use `buildSlot` to analyze the children of the component into
|
|
276
|
-
// WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
|
|
277
|
-
// the core transform context).
|
|
278
|
-
// In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
|
|
279
|
-
// nodes.
|
|
280
|
-
const ssrTransformComponent = (node, context) => {
|
|
281
|
-
if (node.type !== 1 /* ELEMENT */ ||
|
|
282
|
-
node.tagType !== 1 /* COMPONENT */) {
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
|
|
286
|
-
componentTypeMap.set(node, component);
|
|
287
|
-
if (shared.isSymbol(component)) {
|
|
288
|
-
if (component === compilerDom.SUSPENSE) {
|
|
289
|
-
return ssrTransformSuspense(node, context);
|
|
290
|
-
}
|
|
291
|
-
return; // built-in component: fallthrough
|
|
292
|
-
}
|
|
293
|
-
// Build the fallback vnode-based branch for the component's slots.
|
|
294
|
-
// We need to clone the node into a fresh copy and use the buildSlots' logic
|
|
295
|
-
// to get access to the children of each slot. We then compile them with
|
|
296
|
-
// a child transform pipeline using vnode-based transforms (instead of ssr-
|
|
297
|
-
// based ones), and save the result branch (a ReturnStatement) in an array.
|
|
298
|
-
// The branch is retrieved when processing slots again in ssr mode.
|
|
299
|
-
const vnodeBranches = [];
|
|
300
|
-
const clonedNode = clone(node);
|
|
301
|
-
return function ssrPostTransformComponent() {
|
|
302
|
-
// Using the cloned node, build the normal VNode-based branches (for
|
|
303
|
-
// fallback in case the child is render-fn based). Store them in an array
|
|
304
|
-
// for later use.
|
|
305
|
-
if (clonedNode.children.length) {
|
|
306
|
-
compilerDom.buildSlots(clonedNode, context, (props, children) => {
|
|
307
|
-
vnodeBranches.push(createVNodeSlotBranch(props, children, context));
|
|
308
|
-
return compilerDom.createFunctionExpression(undefined);
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
const props = node.props.length > 0
|
|
312
|
-
? // note we are not passing ssr: true here because for components, v-on
|
|
313
|
-
// handlers should still be passed
|
|
314
|
-
compilerDom.buildProps(node, context).props || `null`
|
|
315
|
-
: `null`;
|
|
316
|
-
const wipEntries = [];
|
|
317
|
-
wipMap$1.set(node, wipEntries);
|
|
318
|
-
const buildSSRSlotFn = (props, children, loc) => {
|
|
319
|
-
const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
|
|
320
|
-
true, // newline
|
|
321
|
-
true, // isSlot
|
|
322
|
-
loc);
|
|
323
|
-
wipEntries.push({
|
|
324
|
-
fn,
|
|
325
|
-
children,
|
|
326
|
-
// also collect the corresponding vnode branch built earlier
|
|
327
|
-
vnodeBranch: vnodeBranches[wipEntries.length]
|
|
328
|
-
});
|
|
329
|
-
return fn;
|
|
330
|
-
};
|
|
331
|
-
const slots = node.children.length
|
|
332
|
-
? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots
|
|
333
|
-
: `null`;
|
|
334
|
-
if (typeof component !== 'string') {
|
|
335
|
-
// dynamic component that resolved to a `resolveDynamicComponent` call
|
|
336
|
-
// expression - since the resolved result may be a plain element (string)
|
|
337
|
-
// or a VNode, handle it with `renderVNode`.
|
|
338
|
-
node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_VNODE), [
|
|
339
|
-
`_push`,
|
|
340
|
-
compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
|
|
341
|
-
component,
|
|
342
|
-
props,
|
|
343
|
-
slots
|
|
344
|
-
]),
|
|
345
|
-
`_parent`
|
|
346
|
-
]);
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_COMPONENT), [component, props, slots, `_parent`]);
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
};
|
|
353
|
-
function ssrProcessComponent(node, context) {
|
|
354
|
-
const component = componentTypeMap.get(node);
|
|
355
|
-
if (!node.ssrCodegenNode) {
|
|
356
|
-
// this is a built-in component that fell-through.
|
|
357
|
-
if (component === compilerDom.TELEPORT) {
|
|
358
|
-
return ssrProcessTeleport(node, context);
|
|
359
|
-
}
|
|
360
|
-
else if (component === compilerDom.SUSPENSE) {
|
|
361
|
-
return ssrProcessSuspense(node, context);
|
|
362
|
-
}
|
|
363
|
-
else if (component === compilerDom.TRANSITION_GROUP) {
|
|
364
|
-
return ssrProcessTransitionGroup(node, context);
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
// real fall-through: Transition / KeepAlive
|
|
368
|
-
// just render its children.
|
|
369
|
-
processChildren(node.children, context);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
// finish up slot function expressions from the 1st pass.
|
|
374
|
-
const wipEntries = wipMap$1.get(node) || [];
|
|
375
|
-
for (let i = 0; i < wipEntries.length; i++) {
|
|
376
|
-
const { fn, children, vnodeBranch } = wipEntries[i];
|
|
377
|
-
// For each slot, we generate two branches: one SSR-optimized branch and
|
|
378
|
-
// one normal vnode-based branch. The branches are taken based on the
|
|
379
|
-
// presence of the 2nd `_push` argument (which is only present if the slot
|
|
380
|
-
// is called by `_ssrRenderSlot`.
|
|
381
|
-
fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(children, context, false, true /* withSlotScopeId */), vnodeBranch);
|
|
382
|
-
}
|
|
383
|
-
// component is inside a slot, inherit slot scope Id
|
|
384
|
-
if (context.withSlotScopeId) {
|
|
385
|
-
node.ssrCodegenNode.arguments.push(`_scopeId`);
|
|
386
|
-
}
|
|
387
|
-
if (typeof component === 'string') {
|
|
388
|
-
// static component
|
|
389
|
-
context.pushStatement(compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode]));
|
|
390
|
-
}
|
|
391
|
-
else {
|
|
392
|
-
// dynamic component (`resolveDynamicComponent` call)
|
|
393
|
-
// the codegen node is a `renderVNode` call
|
|
394
|
-
context.pushStatement(node.ssrCodegenNode);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
const rawOptionsMap = new WeakMap();
|
|
399
|
-
const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
|
|
400
|
-
const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
|
|
401
|
-
const vnodeDirectiveTransforms = Object.assign(Object.assign({}, baseDirectiveTransforms), compilerDom.DOMDirectiveTransforms);
|
|
402
|
-
function createVNodeSlotBranch(props, children, parentContext) {
|
|
403
|
-
// apply a sub-transform using vnode-based transforms.
|
|
404
|
-
const rawOptions = rawOptionsMap.get(parentContext.root);
|
|
405
|
-
const subOptions = Object.assign(Object.assign({}, rawOptions), {
|
|
406
|
-
// overwrite with vnode-based transforms
|
|
407
|
-
nodeTransforms: [
|
|
408
|
-
...vnodeNodeTransforms,
|
|
409
|
-
...(rawOptions.nodeTransforms || [])
|
|
410
|
-
], directiveTransforms: Object.assign(Object.assign({}, vnodeDirectiveTransforms), (rawOptions.directiveTransforms || {})) });
|
|
411
|
-
// wrap the children with a wrapper template for proper children treatment.
|
|
412
|
-
const wrapperNode = {
|
|
413
|
-
type: 1 /* ELEMENT */,
|
|
414
|
-
ns: 0 /* HTML */,
|
|
415
|
-
tag: 'template',
|
|
416
|
-
tagType: 3 /* TEMPLATE */,
|
|
417
|
-
isSelfClosing: false,
|
|
418
|
-
// important: provide v-slot="props" on the wrapper for proper
|
|
419
|
-
// scope analysis
|
|
420
|
-
props: [
|
|
421
|
-
{
|
|
422
|
-
type: 7 /* DIRECTIVE */,
|
|
423
|
-
name: 'slot',
|
|
424
|
-
exp: props,
|
|
425
|
-
arg: undefined,
|
|
426
|
-
modifiers: [],
|
|
427
|
-
loc: compilerDom.locStub
|
|
428
|
-
}
|
|
429
|
-
],
|
|
430
|
-
children,
|
|
431
|
-
loc: compilerDom.locStub,
|
|
432
|
-
codegenNode: undefined
|
|
433
|
-
};
|
|
434
|
-
subTransform(wrapperNode, subOptions, parentContext);
|
|
435
|
-
return compilerDom.createReturnStatement(children);
|
|
436
|
-
}
|
|
437
|
-
function subTransform(node, options, parentContext) {
|
|
438
|
-
const childRoot = compilerDom.createRoot([node]);
|
|
439
|
-
const childContext = compilerDom.createTransformContext(childRoot, options);
|
|
440
|
-
// this sub transform is for vnode fallback branch so it should be handled
|
|
441
|
-
// like normal render functions
|
|
442
|
-
childContext.ssr = false;
|
|
443
|
-
// inherit parent scope analysis state
|
|
444
|
-
childContext.scopes = Object.assign({}, parentContext.scopes);
|
|
445
|
-
childContext.identifiers = Object.assign({}, parentContext.identifiers);
|
|
446
|
-
childContext.imports = parentContext.imports;
|
|
447
|
-
// traverse
|
|
448
|
-
compilerDom.traverseNode(childRoot, childContext);
|
|
449
|
-
['helpers', 'components', 'directives'].forEach(key => {
|
|
450
|
-
childContext[key].forEach((value, helperKey) => {
|
|
451
|
-
if (key === 'helpers') {
|
|
452
|
-
const parentCount = parentContext.helpers.get(helperKey);
|
|
453
|
-
if (parentCount === undefined) {
|
|
454
|
-
parentContext.helpers.set(helperKey, value);
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
parentContext.helpers.set(helperKey, value + parentCount);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
parentContext[key].add(value);
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
});
|
|
465
|
-
// imports/hoists are not merged because:
|
|
466
|
-
// - imports are only used for asset urls and should be consistent between
|
|
467
|
-
// node/client branches
|
|
468
|
-
// - hoists are not enabled for the client branch here
|
|
469
|
-
}
|
|
470
|
-
function clone(v) {
|
|
471
|
-
if (shared.isArray(v)) {
|
|
472
|
-
return v.map(clone);
|
|
473
|
-
}
|
|
474
|
-
else if (shared.isObject(v)) {
|
|
475
|
-
const res = {};
|
|
476
|
-
for (const key in v) {
|
|
477
|
-
res[key] = clone(v[key]);
|
|
478
|
-
}
|
|
479
|
-
return res;
|
|
480
|
-
}
|
|
481
|
-
else {
|
|
482
|
-
return v;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
270
|
// for directives with children overwrite (e.g. v-html & v-text), we need to
|
|
487
271
|
// store the raw children so that they can be added in the 2nd pass.
|
|
488
272
|
const rawChildrenMap = new WeakMap();
|
|
@@ -497,14 +281,17 @@ const ssrTransformElement = (node, context) => {
|
|
|
497
281
|
const openTag = [`<${node.tag}`];
|
|
498
282
|
// some tags need to be passed to runtime for special checks
|
|
499
283
|
const needTagForRuntime = node.tag === 'textarea' || node.tag.indexOf('-') > 0;
|
|
500
|
-
// v-bind="obj"
|
|
501
|
-
// attrs and can affect final rendering result,
|
|
502
|
-
// we need to bail out to full `renderAttrs`
|
|
284
|
+
// v-bind="obj", v-bind:[key] and custom directives can potentially
|
|
285
|
+
// overwrite other static attrs and can affect final rendering result,
|
|
286
|
+
// so when they are present we need to bail out to full `renderAttrs`
|
|
503
287
|
const hasDynamicVBind = compilerDom.hasDynamicKeyVBind(node);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
288
|
+
const hasCustomDir = node.props.some(p => p.type === 7 /* DIRECTIVE */ && !shared.isBuiltInDirective(p.name));
|
|
289
|
+
const needMergeProps = hasDynamicVBind || hasCustomDir;
|
|
290
|
+
if (needMergeProps) {
|
|
291
|
+
const { props, directives } = compilerDom.buildProps(node, context, node.props, true /* ssr */);
|
|
292
|
+
if (props || directives.length) {
|
|
293
|
+
const mergedProps = buildSSRProps(props, directives, context);
|
|
294
|
+
const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [mergedProps]);
|
|
508
295
|
if (node.tag === 'textarea') {
|
|
509
296
|
const existingText = node.children[0];
|
|
510
297
|
// If interpolation, this is dynamic <textarea> content, potentially
|
|
@@ -516,7 +303,7 @@ const ssrTransformElement = (node, context) => {
|
|
|
516
303
|
// it contains value (if yes, render is as children).
|
|
517
304
|
const tempId = `_temp${context.temps++}`;
|
|
518
305
|
propsExp.arguments = [
|
|
519
|
-
compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false),
|
|
306
|
+
compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false), mergedProps)
|
|
520
307
|
];
|
|
521
308
|
rawChildrenMap.set(node, compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [
|
|
522
309
|
compilerDom.createConditionalExpression(compilerDom.createSimpleExpression(`"value" in ${tempId}`, false), compilerDom.createSimpleExpression(`${tempId}.value`, false), compilerDom.createSimpleExpression(existingText ? existingText.content : ``, true), false)
|
|
@@ -534,7 +321,7 @@ const ssrTransformElement = (node, context) => {
|
|
|
534
321
|
const tempExp = compilerDom.createSimpleExpression(tempId, false);
|
|
535
322
|
propsExp.arguments = [
|
|
536
323
|
compilerDom.createSequenceExpression([
|
|
537
|
-
compilerDom.createAssignmentExpression(tempExp,
|
|
324
|
+
compilerDom.createAssignmentExpression(tempExp, mergedProps),
|
|
538
325
|
compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), [
|
|
539
326
|
tempExp,
|
|
540
327
|
compilerDom.createCallExpression(context.helper(SSR_GET_DYNAMIC_MODEL_PROPS), [
|
|
@@ -576,11 +363,11 @@ const ssrTransformElement = (node, context) => {
|
|
|
576
363
|
context.onError(compilerDom.createCompilerError(40 /* X_V_SLOT_MISPLACED */, prop.loc));
|
|
577
364
|
}
|
|
578
365
|
else if (isTextareaWithValue(node, prop) && prop.exp) {
|
|
579
|
-
if (!
|
|
366
|
+
if (!needMergeProps) {
|
|
580
367
|
node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
|
|
581
368
|
}
|
|
582
369
|
}
|
|
583
|
-
else if (!
|
|
370
|
+
else if (!needMergeProps) {
|
|
584
371
|
// Directive transforms.
|
|
585
372
|
const directiveTransform = context.directiveTransforms[prop.name];
|
|
586
373
|
if (directiveTransform) {
|
|
@@ -646,7 +433,7 @@ const ssrTransformElement = (node, context) => {
|
|
|
646
433
|
if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {
|
|
647
434
|
rawChildrenMap.set(node, shared.escapeHtml(prop.value.content));
|
|
648
435
|
}
|
|
649
|
-
else if (!
|
|
436
|
+
else if (!needMergeProps) {
|
|
650
437
|
if (prop.name === 'key' || prop.name === 'ref') {
|
|
651
438
|
continue;
|
|
652
439
|
}
|
|
@@ -670,6 +457,30 @@ const ssrTransformElement = (node, context) => {
|
|
|
670
457
|
node.ssrCodegenNode = compilerDom.createTemplateLiteral(openTag);
|
|
671
458
|
};
|
|
672
459
|
};
|
|
460
|
+
function buildSSRProps(props, directives, context) {
|
|
461
|
+
let mergePropsArgs = [];
|
|
462
|
+
if (props) {
|
|
463
|
+
if (props.type === 14 /* JS_CALL_EXPRESSION */) {
|
|
464
|
+
// already a mergeProps call
|
|
465
|
+
mergePropsArgs = props.arguments;
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
mergePropsArgs.push(props);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (directives.length) {
|
|
472
|
+
for (const dir of directives) {
|
|
473
|
+
context.directives.add(dir.name);
|
|
474
|
+
mergePropsArgs.push(compilerDom.createCallExpression(context.helper(SSR_GET_DIRECTIVE_PROPS), [
|
|
475
|
+
`_ctx`,
|
|
476
|
+
...compilerDom.buildDirectiveArgs(dir, context).elements
|
|
477
|
+
]));
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return mergePropsArgs.length > 1
|
|
481
|
+
? compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), mergePropsArgs)
|
|
482
|
+
: mergePropsArgs[0];
|
|
483
|
+
}
|
|
673
484
|
function isTrueFalseValue(prop) {
|
|
674
485
|
if (prop.type === 7 /* DIRECTIVE */) {
|
|
675
486
|
return (prop.name === 'bind' &&
|
|
@@ -730,6 +541,228 @@ function ssrProcessElement(node, context) {
|
|
|
730
541
|
}
|
|
731
542
|
}
|
|
732
543
|
|
|
544
|
+
// We need to construct the slot functions in the 1st pass to ensure proper
|
|
545
|
+
// scope tracking, but the children of each slot cannot be processed until
|
|
546
|
+
// the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
|
|
547
|
+
// pass and complete them in the 2nd pass.
|
|
548
|
+
const wipMap$1 = new WeakMap();
|
|
549
|
+
const componentTypeMap = new WeakMap();
|
|
550
|
+
// ssr component transform is done in two phases:
|
|
551
|
+
// In phase 1. we use `buildSlot` to analyze the children of the component into
|
|
552
|
+
// WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
|
|
553
|
+
// the core transform context).
|
|
554
|
+
// In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
|
|
555
|
+
// nodes.
|
|
556
|
+
const ssrTransformComponent = (node, context) => {
|
|
557
|
+
if (node.type !== 1 /* ELEMENT */ ||
|
|
558
|
+
node.tagType !== 1 /* COMPONENT */) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
|
|
562
|
+
componentTypeMap.set(node, component);
|
|
563
|
+
if (shared.isSymbol(component)) {
|
|
564
|
+
if (component === compilerDom.SUSPENSE) {
|
|
565
|
+
return ssrTransformSuspense(node, context);
|
|
566
|
+
}
|
|
567
|
+
return; // built-in component: fallthrough
|
|
568
|
+
}
|
|
569
|
+
// Build the fallback vnode-based branch for the component's slots.
|
|
570
|
+
// We need to clone the node into a fresh copy and use the buildSlots' logic
|
|
571
|
+
// to get access to the children of each slot. We then compile them with
|
|
572
|
+
// a child transform pipeline using vnode-based transforms (instead of ssr-
|
|
573
|
+
// based ones), and save the result branch (a ReturnStatement) in an array.
|
|
574
|
+
// The branch is retrieved when processing slots again in ssr mode.
|
|
575
|
+
const vnodeBranches = [];
|
|
576
|
+
const clonedNode = clone(node);
|
|
577
|
+
return function ssrPostTransformComponent() {
|
|
578
|
+
// Using the cloned node, build the normal VNode-based branches (for
|
|
579
|
+
// fallback in case the child is render-fn based). Store them in an array
|
|
580
|
+
// for later use.
|
|
581
|
+
if (clonedNode.children.length) {
|
|
582
|
+
compilerDom.buildSlots(clonedNode, context, (props, children) => {
|
|
583
|
+
vnodeBranches.push(createVNodeSlotBranch(props, children, context));
|
|
584
|
+
return compilerDom.createFunctionExpression(undefined);
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
let propsExp = `null`;
|
|
588
|
+
if (node.props.length) {
|
|
589
|
+
// note we are not passing ssr: true here because for components, v-on
|
|
590
|
+
// handlers should still be passed
|
|
591
|
+
const { props, directives } = compilerDom.buildProps(node, context);
|
|
592
|
+
if (props || directives.length) {
|
|
593
|
+
propsExp = buildSSRProps(props, directives, context);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
const wipEntries = [];
|
|
597
|
+
wipMap$1.set(node, wipEntries);
|
|
598
|
+
const buildSSRSlotFn = (props, children, loc) => {
|
|
599
|
+
const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
|
|
600
|
+
true, // newline
|
|
601
|
+
true, // isSlot
|
|
602
|
+
loc);
|
|
603
|
+
wipEntries.push({
|
|
604
|
+
fn,
|
|
605
|
+
children,
|
|
606
|
+
// also collect the corresponding vnode branch built earlier
|
|
607
|
+
vnodeBranch: vnodeBranches[wipEntries.length]
|
|
608
|
+
});
|
|
609
|
+
return fn;
|
|
610
|
+
};
|
|
611
|
+
const slots = node.children.length
|
|
612
|
+
? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots
|
|
613
|
+
: `null`;
|
|
614
|
+
if (typeof component !== 'string') {
|
|
615
|
+
// dynamic component that resolved to a `resolveDynamicComponent` call
|
|
616
|
+
// expression - since the resolved result may be a plain element (string)
|
|
617
|
+
// or a VNode, handle it with `renderVNode`.
|
|
618
|
+
node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_VNODE), [
|
|
619
|
+
`_push`,
|
|
620
|
+
compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
|
|
621
|
+
component,
|
|
622
|
+
propsExp,
|
|
623
|
+
slots
|
|
624
|
+
]),
|
|
625
|
+
`_parent`
|
|
626
|
+
]);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_COMPONENT), [component, propsExp, slots, `_parent`]);
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
};
|
|
633
|
+
function ssrProcessComponent(node, context) {
|
|
634
|
+
const component = componentTypeMap.get(node);
|
|
635
|
+
if (!node.ssrCodegenNode) {
|
|
636
|
+
// this is a built-in component that fell-through.
|
|
637
|
+
if (component === compilerDom.TELEPORT) {
|
|
638
|
+
return ssrProcessTeleport(node, context);
|
|
639
|
+
}
|
|
640
|
+
else if (component === compilerDom.SUSPENSE) {
|
|
641
|
+
return ssrProcessSuspense(node, context);
|
|
642
|
+
}
|
|
643
|
+
else if (component === compilerDom.TRANSITION_GROUP) {
|
|
644
|
+
return ssrProcessTransitionGroup(node, context);
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
// real fall-through: Transition / KeepAlive
|
|
648
|
+
// just render its children.
|
|
649
|
+
processChildren(node.children, context);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
// finish up slot function expressions from the 1st pass.
|
|
654
|
+
const wipEntries = wipMap$1.get(node) || [];
|
|
655
|
+
for (let i = 0; i < wipEntries.length; i++) {
|
|
656
|
+
const { fn, children, vnodeBranch } = wipEntries[i];
|
|
657
|
+
// For each slot, we generate two branches: one SSR-optimized branch and
|
|
658
|
+
// one normal vnode-based branch. The branches are taken based on the
|
|
659
|
+
// presence of the 2nd `_push` argument (which is only present if the slot
|
|
660
|
+
// is called by `_ssrRenderSlot`.
|
|
661
|
+
fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(children, context, false, true /* withSlotScopeId */), vnodeBranch);
|
|
662
|
+
}
|
|
663
|
+
// component is inside a slot, inherit slot scope Id
|
|
664
|
+
if (context.withSlotScopeId) {
|
|
665
|
+
node.ssrCodegenNode.arguments.push(`_scopeId`);
|
|
666
|
+
}
|
|
667
|
+
if (typeof component === 'string') {
|
|
668
|
+
// static component
|
|
669
|
+
context.pushStatement(compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode]));
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
// dynamic component (`resolveDynamicComponent` call)
|
|
673
|
+
// the codegen node is a `renderVNode` call
|
|
674
|
+
context.pushStatement(node.ssrCodegenNode);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const rawOptionsMap = new WeakMap();
|
|
679
|
+
const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
|
|
680
|
+
const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
|
|
681
|
+
const vnodeDirectiveTransforms = Object.assign(Object.assign({}, baseDirectiveTransforms), compilerDom.DOMDirectiveTransforms);
|
|
682
|
+
function createVNodeSlotBranch(props, children, parentContext) {
|
|
683
|
+
// apply a sub-transform using vnode-based transforms.
|
|
684
|
+
const rawOptions = rawOptionsMap.get(parentContext.root);
|
|
685
|
+
const subOptions = Object.assign(Object.assign({}, rawOptions), {
|
|
686
|
+
// overwrite with vnode-based transforms
|
|
687
|
+
nodeTransforms: [
|
|
688
|
+
...vnodeNodeTransforms,
|
|
689
|
+
...(rawOptions.nodeTransforms || [])
|
|
690
|
+
], directiveTransforms: Object.assign(Object.assign({}, vnodeDirectiveTransforms), (rawOptions.directiveTransforms || {})) });
|
|
691
|
+
// wrap the children with a wrapper template for proper children treatment.
|
|
692
|
+
const wrapperNode = {
|
|
693
|
+
type: 1 /* ELEMENT */,
|
|
694
|
+
ns: 0 /* HTML */,
|
|
695
|
+
tag: 'template',
|
|
696
|
+
tagType: 3 /* TEMPLATE */,
|
|
697
|
+
isSelfClosing: false,
|
|
698
|
+
// important: provide v-slot="props" on the wrapper for proper
|
|
699
|
+
// scope analysis
|
|
700
|
+
props: [
|
|
701
|
+
{
|
|
702
|
+
type: 7 /* DIRECTIVE */,
|
|
703
|
+
name: 'slot',
|
|
704
|
+
exp: props,
|
|
705
|
+
arg: undefined,
|
|
706
|
+
modifiers: [],
|
|
707
|
+
loc: compilerDom.locStub
|
|
708
|
+
}
|
|
709
|
+
],
|
|
710
|
+
children,
|
|
711
|
+
loc: compilerDom.locStub,
|
|
712
|
+
codegenNode: undefined
|
|
713
|
+
};
|
|
714
|
+
subTransform(wrapperNode, subOptions, parentContext);
|
|
715
|
+
return compilerDom.createReturnStatement(children);
|
|
716
|
+
}
|
|
717
|
+
function subTransform(node, options, parentContext) {
|
|
718
|
+
const childRoot = compilerDom.createRoot([node]);
|
|
719
|
+
const childContext = compilerDom.createTransformContext(childRoot, options);
|
|
720
|
+
// this sub transform is for vnode fallback branch so it should be handled
|
|
721
|
+
// like normal render functions
|
|
722
|
+
childContext.ssr = false;
|
|
723
|
+
// inherit parent scope analysis state
|
|
724
|
+
childContext.scopes = Object.assign({}, parentContext.scopes);
|
|
725
|
+
childContext.identifiers = Object.assign({}, parentContext.identifiers);
|
|
726
|
+
childContext.imports = parentContext.imports;
|
|
727
|
+
// traverse
|
|
728
|
+
compilerDom.traverseNode(childRoot, childContext);
|
|
729
|
+
['helpers', 'components', 'directives'].forEach(key => {
|
|
730
|
+
childContext[key].forEach((value, helperKey) => {
|
|
731
|
+
if (key === 'helpers') {
|
|
732
|
+
const parentCount = parentContext.helpers.get(helperKey);
|
|
733
|
+
if (parentCount === undefined) {
|
|
734
|
+
parentContext.helpers.set(helperKey, value);
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
parentContext.helpers.set(helperKey, value + parentCount);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
parentContext[key].add(value);
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
});
|
|
745
|
+
// imports/hoists are not merged because:
|
|
746
|
+
// - imports are only used for asset urls and should be consistent between
|
|
747
|
+
// node/client branches
|
|
748
|
+
// - hoists are not enabled for the client branch here
|
|
749
|
+
}
|
|
750
|
+
function clone(v) {
|
|
751
|
+
if (shared.isArray(v)) {
|
|
752
|
+
return v.map(clone);
|
|
753
|
+
}
|
|
754
|
+
else if (shared.isObject(v)) {
|
|
755
|
+
const res = {};
|
|
756
|
+
for (const key in v) {
|
|
757
|
+
res[key] = clone(v[key]);
|
|
758
|
+
}
|
|
759
|
+
return res;
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
return v;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
733
766
|
// Because SSR codegen output is completely different from client-side output
|
|
734
767
|
// (e.g. multiple elements can be concatenated into a single template literal
|
|
735
768
|
// instead of each getting a corresponding call), we need to apply an extra
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/compiler-ssr",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.30",
|
|
4
4
|
"description": "@vue/compiler-ssr",
|
|
5
5
|
"main": "dist/compiler-ssr.cjs.js",
|
|
6
6
|
"types": "dist/compiler-ssr.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-ssr#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@vue/shared": "3.2.
|
|
32
|
-
"@vue/compiler-dom": "3.2.
|
|
31
|
+
"@vue/shared": "3.2.30",
|
|
32
|
+
"@vue/compiler-dom": "3.2.30"
|
|
33
33
|
}
|
|
34
34
|
}
|