0
# Internal Runtime Helpers
1
2
Advanced compilation helpers and internal utilities for custom template compilation and specialized SSR scenarios. These functions are primarily used by Vue's compiler output but can be useful for advanced use cases, custom renderers, and library authors.
3
4
## Capabilities
5
6
### Core Rendering Helpers
7
8
#### ssrRenderVNode
9
10
Core function for rendering individual VNodes to SSR buffer. This is the foundation of all other rendering functions.
11
12
```typescript { .api }
13
/**
14
* Renders a VNode to SSR buffer with optional parent component context
15
* @param vnode - VNode to render
16
* @param parentComponent - Optional parent component instance for context
17
* @param slotScopeId - Optional slot scope ID for scoped slots
18
* @returns SSR buffer or Promise resolving to SSR buffer
19
*/
20
function ssrRenderVNode(
21
vnode: VNode,
22
parentComponent?: ComponentInternalInstance | null,
23
slotScopeId?: string
24
): SSRBuffer | Promise<SSRBuffer>;
25
26
type SSRBuffer = SSRBufferItem[] & { hasAsync?: boolean };
27
type SSRBufferItem = string | SSRBuffer | Promise<SSRBuffer>;
28
type Props = Record<string, unknown>;
29
30
type SSRSlots = Record<string, SSRSlot>;
31
type SSRSlot = (
32
props: Props,
33
push: PushFn,
34
parentComponent: ComponentInternalInstance | null,
35
scopeId: string | null,
36
) => void;
37
38
type PushFn = (item: SSRBufferItem) => void;
39
```
40
41
#### ssrRenderComponent
42
43
Renders a component instance to SSR output.
44
45
```typescript { .api }
46
/**
47
* Renders a component to SSR buffer
48
* @param comp - Component to render
49
* @param props - Component props
50
* @param children - Component children (slots)
51
* @param parentComponent - Parent component context
52
* @param slotScopeId - Slot scope ID
53
* @returns Rendered component output
54
*/
55
function ssrRenderComponent(
56
comp: Component,
57
props: Props | null,
58
children: Slots | SSRSlots | null,
59
parentComponent: ComponentInternalInstance | null,
60
slotScopeId?: string
61
): SSRBuffer | Promise<SSRBuffer>;
62
```
63
64
### Attribute Rendering Helpers
65
66
#### ssrRenderAttrs
67
68
Renders all attributes for an element, handling special cases like class, style, and boolean attributes.
69
70
```typescript { .api }
71
/**
72
* Renders all attributes for an element as a string
73
* @param props - Props object containing attributes
74
* @param tag - Optional HTML tag name for tag-specific handling
75
* @returns String containing all rendered attributes
76
*/
77
function ssrRenderAttrs(
78
props: Record<string, unknown>,
79
tag?: string
80
): string;
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
import { ssrRenderAttrs } from "@vue/server-renderer";
87
88
// Basic attribute rendering
89
const attrs = ssrRenderAttrs({
90
id: 'my-element',
91
class: ['active', 'primary'],
92
'data-value': 42,
93
disabled: true
94
});
95
console.log(attrs);
96
// Output: ' id="my-element" class="active primary" data-value="42" disabled'
97
98
// Tag-specific handling
99
const textareaAttrs = ssrRenderAttrs({
100
value: 'Some text',
101
rows: 10
102
}, 'textarea');
103
// 'value' is excluded for textarea tags
104
```
105
106
#### Individual Attribute Helpers
107
108
```typescript { .api }
109
/**
110
* Renders a single attribute
111
* @param key - Attribute name
112
* @param value - Attribute value
113
* @param tag - Optional HTML tag for context
114
* @returns Rendered attribute string
115
*/
116
function ssrRenderAttr(key: string, value: unknown, tag?: string): string;
117
118
/**
119
* Renders a dynamic attribute with proper escaping
120
* @param key - Attribute name
121
* @param value - Attribute value
122
* @param tag - Optional HTML tag for context
123
* @returns Rendered attribute string
124
*/
125
function ssrRenderDynamicAttr(key: string, value: unknown, tag?: string): string;
126
127
/**
128
* Renders class attribute with array/object support
129
* @param value - Class value (string, array, or object)
130
* @returns Normalized class string
131
*/
132
function ssrRenderClass(value: unknown): string;
133
134
/**
135
* Renders style attribute with object support
136
* @param value - Style value (string or object)
137
* @returns Normalized style string
138
*/
139
function ssrRenderStyle(value: unknown): string;
140
```
141
142
### Content Rendering Helpers
143
144
#### ssrInterpolate
145
146
Safely interpolates values for SSR output with proper HTML escaping.
147
148
```typescript { .api }
149
/**
150
* Safely interpolates a value for SSR output
151
* @param value - Value to interpolate
152
* @returns HTML-escaped string representation
153
*/
154
function ssrInterpolate(value: unknown): string;
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import { ssrInterpolate } from "@vue/server-renderer";
161
162
// Safe interpolation with escaping
163
console.log(ssrInterpolate('<script>alert("xss")</script>'));
164
// Output: "<script>alert("xss")</script>"
165
166
console.log(ssrInterpolate({ name: 'John', age: 30 }));
167
// Output: "[object Object]"
168
169
console.log(ssrInterpolate(['a', 'b', 'c']));
170
// Output: "a,b,c"
171
172
console.log(ssrInterpolate(null));
173
// Output: ""
174
175
console.log(ssrInterpolate(undefined));
176
// Output: ""
177
```
178
179
#### ssrRenderList
180
181
Renders v-for loops in SSR context.
182
183
```typescript { .api }
184
/**
185
* Renders a list using v-for logic
186
* @param source - Source data (array, object, string, or number)
187
* @param renderItem - Function to render each item
188
* @returns Array of rendered items
189
*/
190
function ssrRenderList(
191
source: any,
192
renderItem: (value: any, key: any, index: number) => any
193
): any[];
194
```
195
196
**Usage Examples:**
197
198
```typescript
199
import { ssrRenderList, ssrInterpolate } from "@vue/server-renderer";
200
201
// Render array
202
const items = ['apple', 'banana', 'cherry'];
203
const listHtml = ssrRenderList(items, (item, index) => {
204
return `<li key="${index}">${ssrInterpolate(item)}</li>`;
205
}).join('');
206
console.log(listHtml);
207
// Output: <li key="0">apple</li><li key="1">banana</li><li key="2">cherry</li>
208
209
// Render object
210
const user = { name: 'John', age: 30, city: 'New York' };
211
const userFields = ssrRenderList(user, (value, key) => {
212
return `<div>${key}: ${ssrInterpolate(value)}</div>`;
213
}).join('');
214
```
215
216
### Slot and Teleport Helpers
217
218
#### ssrRenderSlot
219
220
Renders slot content in SSR context.
221
222
```typescript { .api }
223
/**
224
* Renders slot content with fallback support
225
* @param slots - Slots object (regular or SSR slots)
226
* @param slotName - Slot name
227
* @param slotProps - Props to pass to slot
228
* @param fallbackRenderFn - Fallback content function
229
* @param push - Push function for SSR buffer
230
* @param parentComponent - Parent component context
231
* @param slotScopeId - Slot scope ID
232
*/
233
function ssrRenderSlot(
234
slots: Slots | SSRSlots,
235
slotName: string,
236
slotProps: Props,
237
fallbackRenderFn: (() => void) | null,
238
push: PushFn,
239
parentComponent: ComponentInternalInstance,
240
slotScopeId?: string
241
): void;
242
243
/**
244
* Internal slot rendering helper without fragment wrapping
245
* @param slots - Slots object (regular or SSR slots)
246
* @param slotName - Slot name
247
* @param slotProps - Props to pass to slot
248
* @param fallbackRenderFn - Fallback content function
249
* @param push - Push function for SSR buffer
250
* @param parentComponent - Parent component context
251
* @param slotScopeId - Slot scope ID
252
* @param transition - Whether slot is in transition
253
*/
254
function ssrRenderSlotInner(
255
slots: Slots | SSRSlots,
256
slotName: string,
257
slotProps: Props,
258
fallbackRenderFn: (() => void) | null,
259
push: PushFn,
260
parentComponent: ComponentInternalInstance,
261
slotScopeId?: string,
262
transition?: boolean
263
): void;
264
```
265
266
#### ssrRenderTeleport
267
268
Handles teleport components in SSR context.
269
270
```typescript { .api }
271
/**
272
* Renders teleport content to appropriate targets
273
* @param parentPush - Parent push function
274
* @param content - Teleport content renderer
275
* @param target - Teleport target selector
276
* @param disabled - Whether teleport is disabled
277
* @param parentComponent - Parent component context
278
*/
279
function ssrRenderTeleport(
280
parentPush: PushFn,
281
content: () => void,
282
target: string | null,
283
disabled: boolean,
284
parentComponent: ComponentInternalInstance
285
): void;
286
```
287
288
#### ssrRenderSuspense
289
290
Handles Suspense components in SSR context.
291
292
```typescript { .api }
293
/**
294
* Renders Suspense component with async content handling
295
* @param push - Push function for SSR buffer
296
* @param suspenseInstance - Suspense component instance
297
*/
298
function ssrRenderSuspense(
299
push: PushFn,
300
suspenseInstance: ComponentInternalInstance
301
): void;
302
```
303
304
### Form Input Helpers
305
306
#### v-model Helpers
307
308
Special helpers for handling v-model directives in SSR context.
309
310
```typescript { .api }
311
/**
312
* Loose equality comparison for v-model
313
* @param a - First value
314
* @param b - Second value
315
* @returns Whether values are loosely equal
316
*/
317
function ssrLooseEqual(a: unknown, b: unknown): boolean;
318
319
/**
320
* Checks if array loosely contains a value
321
* @param arr - Array to search
322
* @param value - Value to find
323
* @returns Whether array contains the value
324
*/
325
function ssrLooseContain(arr: unknown[], value: unknown): boolean;
326
327
/**
328
* Renders dynamic v-model attributes based on input type
329
* @param type - Input type (radio, checkbox, etc.)
330
* @param model - Model value
331
* @param value - Input value
332
* @returns Appropriate attribute string
333
*/
334
function ssrRenderDynamicModel(
335
type: unknown,
336
model: unknown,
337
value: unknown
338
): string;
339
340
/**
341
* Gets dynamic model properties for v-bind + v-model
342
* @param existingProps - Existing props object
343
* @param model - Model value
344
* @returns Properties to merge with existing props
345
*/
346
function ssrGetDynamicModelProps(
347
existingProps: any,
348
model: unknown
349
): { checked: true } | { value: any } | null;
350
```
351
352
**Usage Examples:**
353
354
```typescript
355
import {
356
ssrRenderDynamicModel,
357
ssrGetDynamicModelProps
358
} from "@vue/server-renderer";
359
360
// Radio button v-model
361
const radioAttr = ssrRenderDynamicModel('radio', 'selected', 'option1');
362
console.log(radioAttr); // ' checked' if model === 'option1'
363
364
// Checkbox v-model with array
365
const checkboxAttr = ssrRenderDynamicModel('checkbox', ['a', 'b'], 'b');
366
console.log(checkboxAttr); // ' checked'
367
368
// Dynamic props
369
const props = ssrGetDynamicModelProps({ type: 'text' }, 'hello');
370
console.log(props); // { value: 'hello' }
371
```
372
373
### Directive Helpers
374
375
#### ssrGetDirectiveProps
376
377
Extracts props from directive bindings for SSR rendering.
378
379
```typescript { .api }
380
/**
381
* Extracts props from directive bindings
382
* @param instance - Component instance
383
* @param dir - Directive binding
384
* @param value - Directive value
385
* @param arg - Directive argument
386
* @param modifiers - Directive modifiers
387
* @returns Props object from directive
388
*/
389
function ssrGetDirectiveProps(
390
instance: ComponentInternalInstance,
391
dir: DirectiveBinding,
392
value?: any,
393
arg?: string,
394
modifiers?: Record<string, boolean>
395
): Record<string, any> | null;
396
```
397
398
#### ssrIncludeBooleanAttr
399
400
Determines whether boolean attributes should be included.
401
402
```typescript { .api }
403
/**
404
* Determines if a boolean attribute should be included
405
* @param value - Attribute value
406
* @returns Whether to include the attribute
407
*/
408
function ssrIncludeBooleanAttr(value: unknown): boolean;
409
```
410
411
## Advanced Usage Examples
412
413
### Custom Renderer
414
415
```typescript
416
import {
417
ssrRenderVNode,
418
ssrRenderAttrs,
419
ssrInterpolate
420
} from "@vue/server-renderer";
421
import { h } from "vue";
422
423
// Custom rendering function
424
async function customRender(vnode: VNode): Promise<string> {
425
const buffer = await ssrRenderVNode(vnode);
426
427
// Convert buffer to string (simplified)
428
function bufferToString(buf: SSRBuffer): string {
429
return buf.map(item =>
430
typeof item === 'string' ? item : bufferToString(item)
431
).join('');
432
}
433
434
return bufferToString(buffer);
435
}
436
437
// Usage
438
const vnode = h('div', { class: 'custom' }, [
439
h('h1', 'Custom Renderer'),
440
h('p', 'Rendered with internal helpers')
441
]);
442
443
const html = await customRender(vnode);
444
```
445
446
### Template Compilation Integration
447
448
```typescript
449
import {
450
ssrRenderAttrs,
451
ssrInterpolate,
452
ssrRenderList
453
} from "@vue/server-renderer";
454
455
// Compiled template function (generated by Vue compiler)
456
function render(_ctx: any, _push: PushFn) {
457
_push('<div');
458
_push(ssrRenderAttrs({
459
class: _ctx.containerClass,
460
id: _ctx.elementId
461
}));
462
_push('>');
463
464
_push('<h1>');
465
_push(ssrInterpolate(_ctx.title));
466
_push('</h1>');
467
468
_push('<ul>');
469
ssrRenderList(_ctx.items, (item, index) => {
470
_push('<li key="');
471
_push(ssrInterpolate(index));
472
_push('">');
473
_push(ssrInterpolate(item.name));
474
_push('</li>');
475
});
476
_push('</ul>');
477
478
_push('</div>');
479
}
480
```
481
482
### Performance Optimization
483
484
```typescript
485
import { ssrRenderAttrs, ssrInterpolate } from "@vue/server-renderer";
486
487
// Cache frequently used attribute combinations
488
const attrCache = new Map();
489
490
function cachedRenderAttrs(props: Record<string, unknown>): string {
491
const key = JSON.stringify(props);
492
if (!attrCache.has(key)) {
493
attrCache.set(key, ssrRenderAttrs(props));
494
}
495
return attrCache.get(key);
496
}
497
498
// Batch interpolation for arrays
499
function batchInterpolate(values: unknown[]): string[] {
500
return values.map(ssrInterpolate);
501
}
502
```
503
504
## Security Considerations
505
506
All internal helpers include proper HTML escaping and XSS protection:
507
508
```typescript
509
import { ssrInterpolate, ssrRenderAttrs } from "@vue/server-renderer";
510
511
// All user content is automatically escaped
512
const userInput = '<script>alert("xss")</script>';
513
const safeOutput = ssrInterpolate(userInput);
514
// Output: "<script>alert("xss")</script>"
515
516
// Attribute values are also escaped
517
const attrs = ssrRenderAttrs({
518
title: 'Hello "world"',
519
'data-content': '<div>content</div>'
520
});
521
// Output: ' title="Hello "world"" data-content="<div>content</div>"'
522
```
523
524
## Integration Notes
525
526
These helpers are designed to work with:
527
- Vue's template compiler output
528
- Custom rendering systems
529
- Server-side template engines
530
- Build-time optimizations
531
- Development tools and debugging
532
533
They provide the building blocks for all higher-level rendering functions and maintain consistency with Vue's client-side rendering behavior.