Skip to content

Commit 535c829

Browse files
authored
fix: reactive in SSR (#546)
* chore: add failed tests * fix: workaround * chore: export toRaw
1 parent 3a1d992 commit 535c829

File tree

6 files changed

+86
-30
lines changed

6 files changed

+86
-30
lines changed

src/apis/index.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,26 @@
1-
export * from './state'
1+
export {
2+
isReactive,
3+
isRef,
4+
isRaw,
5+
markRaw,
6+
reactive,
7+
ref,
8+
customRef,
9+
Ref,
10+
set,
11+
shallowReactive,
12+
shallowRef,
13+
toRaw,
14+
toRef,
15+
toRefs,
16+
triggerRef,
17+
unref,
18+
UnwrapRef,
19+
isReadonly,
20+
shallowReadonly,
21+
proxyRefs,
22+
ShallowUnwrapRef,
23+
} from '../reactivity'
224
export * from './lifecycle'
325
export * from './watch'
426
export * from './computed'

src/apis/state.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/reactivity/reactive.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AnyObject } from '../types/basic'
22
import { getRegisteredVueOrDefault } from '../runtimeContext'
3-
import { isPlainObject, def, warn } from '../utils'
3+
import { isPlainObject, def, warn, hasOwn } from '../utils'
44
import { isComponentInstance, defineComponentInstance } from '../utils/helper'
55
import { RefKey } from '../utils/symbols'
66
import { isRef, UnwrapRef } from './ref'
@@ -111,6 +111,11 @@ function observe<T>(obj: T): T {
111111
observed = vm._data.$$state
112112
}
113113

114+
// in SSR, there is no __ob__. Mock for reactivity check
115+
if (!hasOwn(observed, '__ob__')) {
116+
def(observed, '__ob__', {})
117+
}
118+
114119
return observed
115120
}
116121

@@ -154,7 +159,7 @@ export function shallowReactive(obj: any): any {
154159
configurable: true,
155160
get: function getterHandler() {
156161
const value = getter ? getter.call(obj) : val
157-
ob.dep.depend()
162+
ob.dep?.depend()
158163
return value
159164
},
160165
set: function setterHandler(newVal) {
@@ -164,7 +169,7 @@ export function shallowReactive(obj: any): any {
164169
} else {
165170
val = newVal
166171
}
167-
ob.dep.notify()
172+
ob.dep?.notify()
168173
},
169174
})
170175
}

test/helpers/wait-for-update.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const Vue = require('vue')
1313
// })
1414
// .then(done)
1515

16-
window.waitForUpdate = (initialCb) => {
16+
const waitForUpdate = (initialCb) => {
1717
let end
1818
const queue = initialCb ? [initialCb] : []
1919

@@ -69,7 +69,11 @@ window.waitForUpdate = (initialCb) => {
6969
return chainer
7070
}
7171

72-
exports.waitForUpdate = window.waitForUpdate
72+
if (typeof window !== 'undefined') {
73+
window.waitForUpdate = waitForUpdate
74+
}
75+
76+
exports.waitForUpdate = waitForUpdate
7377

7478
function timeout(n) {
7579
return (next) => setTimeout(next, n)

test/ssr/serverPrefetch.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const {
44
ref,
55
onServerPrefetch,
66
getCurrentInstance,
7-
provide,
8-
inject,
7+
isReactive,
8+
reactive,
99
} = require('../../src')
1010

1111
function fetch(result) {

test/ssr/ssrReactive.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
import Vue from '../vue'
6+
import { isReactive, reactive, ref, isRaw, isRef, shallowRef } from '../../src'
7+
import { createRenderer } from 'vue-server-renderer'
8+
9+
describe('SSR Reactive', () => {
10+
beforeEach(() => {
11+
process.env.VUE_ENV = 'server'
12+
})
13+
14+
it('should in SSR context', async () => {
15+
expect(typeof window).toBe('undefined')
16+
expect((Vue.observable({}) as any).__ob__).toBeUndefined()
17+
})
18+
19+
it('should render', async () => {
20+
const app = new Vue({
21+
setup() {
22+
return {
23+
count: ref(42),
24+
}
25+
},
26+
render(this: any, h) {
27+
return h('div', this.count)
28+
},
29+
})
30+
31+
const serverRenderer = createRenderer()
32+
const html = await serverRenderer.renderToString(app)
33+
expect(html).toBe('<div data-server-rendered="true">42</div>')
34+
})
35+
36+
it('reactive + isReactive', async () => {
37+
const state = reactive({})
38+
expect(isReactive(state)).toBe(true)
39+
expect(isRaw(state)).toBe(false)
40+
})
41+
42+
it('shallowRef + isRef', async () => {
43+
const state = shallowRef({})
44+
expect(isRef(state)).toBe(true)
45+
expect(isRaw(state)).toBe(false)
46+
})
47+
})

0 commit comments

Comments
 (0)