Skip to content

Commit 38f0269

Browse files
committed
refactor: simplify suspense ssr + adjust behavior
1 parent eb5b32f commit 38f0269

File tree

7 files changed

+131
-223
lines changed

7 files changed

+131
-223
lines changed

packages/compiler-ssr/__tests__/ssrSuspense.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ describe('ssr compile: suspense', () => {
99
return function ssrRender(_ctx, _push, _parent) {
1010
const _component_foo = _resolveComponent(\\"foo\\")
1111
12-
_push(_ssrRenderSuspense({
13-
default: (_push) => {
12+
_ssrRenderSuspense(_push, {
13+
default: () => {
1414
_push(_ssrRenderComponent(_component_foo, null, null, _parent))
1515
},
1616
_: 1
17-
}))
17+
})
1818
}"
1919
`)
2020
})
@@ -36,15 +36,15 @@ describe('ssr compile: suspense', () => {
3636
return function ssrRender(_ctx, _push, _parent) {
3737
const _component_foo = _resolveComponent(\\"foo\\")
3838
39-
_push(_ssrRenderSuspense({
40-
default: (_push) => {
39+
_ssrRenderSuspense(_push, {
40+
default: () => {
4141
_push(_ssrRenderComponent(_component_foo, null, null, _parent))
4242
},
43-
fallback: (_push) => {
43+
fallback: () => {
4444
_push(\` loading... \`)
4545
},
4646
_: 1
47-
}))
47+
})
4848
}"
4949
`)
5050
})

packages/compiler-ssr/src/transforms/ssrTransformSuspense.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function ssrTransformSuspense(
3838
wipMap.set(node, wipEntry)
3939
wipEntry.slotsExp = buildSlots(node, context, (_props, children, loc) => {
4040
const fn = createFunctionExpression(
41-
[`_push`],
41+
[],
4242
undefined, // no return, assign body later
4343
true, // newline
4444
false, // suspense slots are not treated as normal slots
@@ -71,8 +71,9 @@ export function ssrProcessSuspense(
7171
}
7272
// _push(ssrRenderSuspense(slots))
7373
context.pushStatement(
74-
createCallExpression(`_push`, [
75-
createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [slotsExp])
74+
createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [
75+
`_push`,
76+
slotsExp
7677
])
7778
)
7879
}

packages/runtime-core/__tests__/component.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import {
66
nextTick,
77
defineComponent
88
} from '@vue/runtime-test'
9+
import { mockWarn } from '@vue/shared'
910

1011
describe('renderer: component', () => {
12+
mockWarn()
13+
1114
test.todo('should work')
1215

1316
test.todo('shouldUpdateComponent')
@@ -40,6 +43,7 @@ describe('renderer: component', () => {
4043
expect(b1).toBe(true)
4144
expect(b2).toBe(true)
4245
expect(b3).toBe('')
46+
expect('type check failed for prop "b1"').toHaveBeenWarned()
4347
})
4448
})
4549

packages/server-renderer/__tests__/renderToString.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import {
88
ref,
99
defineComponent
1010
} from 'vue'
11-
import { escapeHtml, mockError } from '@vue/shared'
11+
import { escapeHtml, mockWarn } from '@vue/shared'
1212
import { renderToString, renderComponent } from '../src/renderToString'
1313
import { ssrRenderSlot } from '../src/helpers/ssrRenderSlot'
1414

15-
mockError()
15+
mockWarn()
1616

1717
describe('ssr: renderToString', () => {
1818
test('should apply app context', async () => {
Lines changed: 89 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { createApp, h, Suspense } from 'vue'
22
import { renderToString } from '../src/renderToString'
3-
import { ssrRenderSuspense } from '../src/helpers/ssrRenderSuspense'
4-
import { ssrRenderComponent } from '../src'
5-
import { mockError } from '@vue/shared'
3+
import { mockWarn } from '@vue/shared'
64

75
describe('SSR Suspense', () => {
8-
mockError()
6+
mockWarn()
97

108
const ResolvingAsync = {
119
async setup() {
@@ -19,161 +17,109 @@ describe('SSR Suspense', () => {
1917
}
2018
}
2119

22-
describe('compiled', () => {
23-
test('basic', async () => {
24-
const app = createApp({
25-
ssrRender(_ctx, _push) {
26-
_push(
27-
ssrRenderSuspense({
28-
default: _push => {
29-
_push('<div>async</div>')
30-
}
31-
})
32-
)
33-
}
34-
})
35-
36-
expect(await renderToString(app)).toBe(`<!--[--><div>async</div><!--]-->`)
37-
})
38-
39-
test('with async component', async () => {
40-
const app = createApp({
41-
ssrRender(_ctx, _push) {
42-
_push(
43-
ssrRenderSuspense({
44-
default: _push => {
45-
_push(ssrRenderComponent(ResolvingAsync))
46-
}
47-
})
48-
)
49-
}
50-
})
51-
52-
expect(await renderToString(app)).toBe(`<!--[--><div>async</div><!--]-->`)
53-
})
54-
55-
test('fallback', async () => {
56-
const app = createApp({
57-
ssrRender(_ctx, _push) {
58-
_push(
59-
ssrRenderSuspense({
60-
default: _push => {
61-
_push(ssrRenderComponent(RejectingAsync))
62-
},
63-
fallback: _push => {
64-
_push('<div>fallback</div>')
65-
}
66-
})
67-
)
68-
}
69-
})
70-
71-
expect(await renderToString(app)).toBe(
72-
`<!--[--><div>fallback</div><!--]-->`
73-
)
74-
expect('Uncaught error in async setup').toHaveBeenWarned()
75-
})
76-
})
77-
78-
describe('vnode', () => {
79-
test('content', async () => {
80-
const Comp = {
81-
render() {
82-
return h(Suspense, null, {
83-
default: h(ResolvingAsync),
84-
fallback: h('div', 'fallback')
85-
})
86-
}
20+
test('content', async () => {
21+
const Comp = {
22+
render() {
23+
return h(Suspense, null, {
24+
default: h(ResolvingAsync),
25+
fallback: h('div', 'fallback')
26+
})
8727
}
28+
}
8829

89-
expect(await renderToString(createApp(Comp))).toBe(`<div>async</div>`)
90-
})
30+
expect(await renderToString(createApp(Comp))).toBe(`<div>async</div>`)
31+
})
9132

92-
test('fallback', async () => {
93-
const Comp = {
94-
render() {
95-
return h(Suspense, null, {
96-
default: h(RejectingAsync),
97-
fallback: h('div', 'fallback')
98-
})
99-
}
33+
test('reject', async () => {
34+
const Comp = {
35+
render() {
36+
return h(Suspense, null, {
37+
default: h(RejectingAsync),
38+
fallback: h('div', 'fallback')
39+
})
10040
}
41+
}
10142

102-
expect(await renderToString(createApp(Comp))).toBe(`<div>fallback</div>`)
103-
expect('Uncaught error in async setup').toHaveBeenWarned()
104-
})
43+
expect(await renderToString(createApp(Comp))).toBe(`<!---->`)
44+
expect('Uncaught error in async setup').toHaveBeenWarned()
45+
expect('missing template').toHaveBeenWarned()
46+
})
10547

106-
test('2 components', async () => {
107-
const Comp = {
108-
render() {
109-
return h(Suspense, null, {
110-
default: h('div', [h(ResolvingAsync), h(ResolvingAsync)]),
111-
fallback: h('div', 'fallback')
112-
})
113-
}
48+
test('2 components', async () => {
49+
const Comp = {
50+
render() {
51+
return h(Suspense, null, {
52+
default: h('div', [h(ResolvingAsync), h(ResolvingAsync)]),
53+
fallback: h('div', 'fallback')
54+
})
11455
}
56+
}
11557

116-
expect(await renderToString(createApp(Comp))).toBe(
117-
`<div><div>async</div><div>async</div></div>`
118-
)
119-
})
58+
expect(await renderToString(createApp(Comp))).toBe(
59+
`<div><div>async</div><div>async</div></div>`
60+
)
61+
})
12062

121-
test('resolving component + rejecting component', async () => {
122-
const Comp = {
123-
render() {
124-
return h(Suspense, null, {
125-
default: h('div', [h(ResolvingAsync), h(RejectingAsync)]),
126-
fallback: h('div', 'fallback')
127-
})
128-
}
63+
test('resolving component + rejecting component', async () => {
64+
const Comp = {
65+
render() {
66+
return h(Suspense, null, {
67+
default: h('div', [h(ResolvingAsync), h(RejectingAsync)]),
68+
fallback: h('div', 'fallback')
69+
})
12970
}
71+
}
13072

131-
expect(await renderToString(createApp(Comp))).toBe(`<div>fallback</div>`)
132-
expect('Uncaught error in async setup').toHaveBeenWarned()
133-
})
73+
expect(await renderToString(createApp(Comp))).toBe(
74+
`<div><div>async</div><!----></div>`
75+
)
76+
expect('Uncaught error in async setup').toHaveBeenWarned()
77+
expect('missing template or render function').toHaveBeenWarned()
78+
})
13479

135-
test('failing suspense in passing suspense', async () => {
136-
const Comp = {
137-
render() {
138-
return h(Suspense, null, {
139-
default: h('div', [
140-
h(ResolvingAsync),
141-
h(Suspense, null, {
142-
default: h('div', [h(RejectingAsync)]),
143-
fallback: h('div', 'fallback 2')
144-
})
145-
]),
146-
fallback: h('div', 'fallback 1')
147-
})
148-
}
80+
test('failing suspense in passing suspense', async () => {
81+
const Comp = {
82+
render() {
83+
return h(Suspense, null, {
84+
default: h('div', [
85+
h(ResolvingAsync),
86+
h(Suspense, null, {
87+
default: h('div', [h(RejectingAsync)]),
88+
fallback: h('div', 'fallback 2')
89+
})
90+
]),
91+
fallback: h('div', 'fallback 1')
92+
})
14993
}
94+
}
15095

151-
expect(await renderToString(createApp(Comp))).toBe(
152-
`<div><div>async</div><div>fallback 2</div></div>`
153-
)
154-
expect('Uncaught error in async setup').toHaveBeenWarned()
155-
})
96+
expect(await renderToString(createApp(Comp))).toBe(
97+
`<div><div>async</div><div><!----></div></div>`
98+
)
99+
expect('Uncaught error in async setup').toHaveBeenWarned()
100+
expect('missing template').toHaveBeenWarned()
101+
})
156102

157-
test('passing suspense in failing suspense', async () => {
158-
const Comp = {
159-
render() {
160-
return h(Suspense, null, {
161-
default: h('div', [
162-
h(RejectingAsync),
163-
h(Suspense, null, {
164-
default: h('div', [h(ResolvingAsync)]),
165-
fallback: h('div', 'fallback 2')
166-
})
167-
]),
168-
fallback: h('div', 'fallback 1')
169-
})
170-
}
103+
test('passing suspense in failing suspense', async () => {
104+
const Comp = {
105+
render() {
106+
return h(Suspense, null, {
107+
default: h('div', [
108+
h(RejectingAsync),
109+
h(Suspense, null, {
110+
default: h('div', [h(ResolvingAsync)]),
111+
fallback: h('div', 'fallback 2')
112+
})
113+
]),
114+
fallback: h('div', 'fallback 1')
115+
})
171116
}
117+
}
172118

173-
expect(await renderToString(createApp(Comp))).toBe(
174-
`<div>fallback 1</div>`
175-
)
176-
expect('Uncaught error in async setup').toHaveBeenWarned()
177-
})
119+
expect(await renderToString(createApp(Comp))).toBe(
120+
`<div><!----><div><div>async</div></div></div>`
121+
)
122+
expect('Uncaught error in async setup').toHaveBeenWarned()
123+
expect('missing template').toHaveBeenWarned()
178124
})
179125
})
Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
1-
import { PushFn, ResolvedSSRBuffer, createBuffer } from '../renderToString'
1+
import { PushFn } from '../renderToString'
22

3-
type ContentRenderFn = (push: PushFn) => void
4-
5-
export async function ssrRenderSuspense({
6-
default: renderContent,
7-
fallback: renderFallback
8-
}: Record<string, ContentRenderFn | undefined>): Promise<ResolvedSSRBuffer> {
9-
try {
10-
if (renderContent) {
11-
const { push, getBuffer } = createBuffer()
12-
push(`<!--[-->`)
13-
renderContent(push)
14-
push(`<!--]-->`)
15-
return await getBuffer()
16-
} else {
17-
return []
18-
}
19-
} catch {
20-
if (renderFallback) {
21-
const { push, getBuffer } = createBuffer()
22-
push(`<!--[-->`)
23-
renderFallback(push)
24-
push(`<!--]-->`)
25-
return getBuffer()
26-
} else {
27-
return []
28-
}
3+
export async function ssrRenderSuspense(
4+
push: PushFn,
5+
{ default: renderContent }: Record<string, (() => void) | undefined>
6+
) {
7+
if (renderContent) {
8+
push(`<!--[-->`)
9+
renderContent()
10+
push(`<!--]-->`)
11+
} else {
12+
push(`<!---->`)
2913
}
3014
}

0 commit comments

Comments
 (0)