Skip to content

Commit bc07e95

Browse files
committed
fix(ssr): avoid hard-coded ssr checks in cjs builds
1 parent 6b1ce00 commit bc07e95

File tree

8 files changed

+31
-19
lines changed

8 files changed

+31
-19
lines changed

jest.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module.exports = {
77
__BROWSER__: false,
88
__BUNDLER__: true,
99
__RUNTIME_COMPILE__: true,
10-
__SSR__: false,
10+
__NODE_JS__: true,
1111
__FEATURE_OPTIONS__: true,
1212
__FEATURE_SUSPENSE__: true
1313
},

packages/global.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ declare var __TEST__: boolean
44
declare var __BROWSER__: boolean
55
declare var __BUNDLER__: boolean
66
declare var __RUNTIME_COMPILE__: boolean
7-
declare var __SSR__: boolean
7+
declare var __NODE_JS__: boolean
88
declare var __COMMIT__: string
99
declare var __VERSION__: string
1010

packages/runtime-core/src/apiLifecycle.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import {
22
ComponentInternalInstance,
33
LifecycleHooks,
44
currentInstance,
5-
setCurrentInstance
5+
setCurrentInstance,
6+
isInSSRComponentSetup
67
} from './component'
78
import { ComponentPublicInstance } from './componentProxy'
89
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
@@ -66,7 +67,7 @@ export const createHook = <T extends Function = () => any>(
6667
lifecycle: LifecycleHooks
6768
) => (hook: T, target: ComponentInternalInstance | null = currentInstance) =>
6869
// post-create lifecycle registrations are noops during SSR
69-
!__SSR__ && injectHook(lifecycle, hook, target)
70+
!isInSSRComponentSetup && injectHook(lifecycle, hook, target)
7071

7172
export const onBeforeMount = createHook(LifecycleHooks.BEFORE_MOUNT)
7273
export const onMounted = createHook(LifecycleHooks.MOUNTED)

packages/runtime-core/src/apiWatch.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import {
2121
currentInstance,
2222
ComponentInternalInstance,
2323
currentSuspense,
24-
Data
24+
Data,
25+
isInSSRComponentSetup
2526
} from './component'
2627
import {
2728
ErrorCodes,
@@ -86,8 +87,8 @@ export function watch<T = any>(
8687
cbOrOptions?: WatchCallback<T> | WatchOptions,
8788
options?: WatchOptions
8889
): StopHandle {
89-
if (__SSR__ && !(options && options.flush === 'sync')) {
90-
// during SSR, non-sync watchers never fire.
90+
if (isInSSRComponentSetup && !(options && options.flush === 'sync')) {
91+
// component watchers during SSR are no-op
9192
return NOOP
9293
} else if (isFunction(cbOrOptions)) {
9394
// effect callback as 2nd argument - this is a source watcher

packages/runtime-core/src/component.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -269,19 +269,26 @@ export function validateComponentName(name: string, config: AppConfig) {
269269
}
270270
}
271271

272+
export let isInSSRComponentSetup = false
273+
272274
export function setupComponent(
273275
instance: ComponentInternalInstance,
274-
parentSuspense: SuspenseBoundary | null
276+
parentSuspense: SuspenseBoundary | null,
277+
isSSR = false
275278
) {
279+
isInSSRComponentSetup = isSSR
276280
const propsOptions = instance.type.props
277281
const { props, children, shapeFlag } = instance.vnode
278282
resolveProps(instance, props, propsOptions)
279283
resolveSlots(instance, children)
280284

281285
// setup stateful logic
286+
let setupResult
282287
if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
283-
return setupStatefulComponent(instance, parentSuspense)
288+
setupResult = setupStatefulComponent(instance, parentSuspense)
284289
}
290+
isInSSRComponentSetup = false
291+
return setupResult
285292
}
286293

287294
function setupStatefulComponent(
@@ -314,7 +321,7 @@ function setupStatefulComponent(
314321
// 2. create props proxy
315322
// the propsProxy is a reactive AND readonly proxy to the actual props.
316323
// it will be updated in resolveProps() on updates before render
317-
const propsProxy = (instance.propsProxy = __SSR__
324+
const propsProxy = (instance.propsProxy = isInSSRComponentSetup
318325
? instance.props
319326
: shallowReadonly(instance.props))
320327
// 3. call setup()
@@ -335,7 +342,7 @@ function setupStatefulComponent(
335342
currentSuspense = null
336343

337344
if (isPromise(setupResult)) {
338-
if (__SSR__) {
345+
if (isInSSRComponentSetup) {
339346
// return the promise so server-renderer can wait on it
340347
return setupResult.then(resolvedResult => {
341348
handleSetupResult(instance, resolvedResult, parentSuspense)
@@ -413,15 +420,15 @@ function finishComponentSetup(
413420
;(Component.render as RenderFunction).isRuntimeCompiled = true
414421
}
415422

416-
if (__DEV__ && !Component.render) {
423+
if (__DEV__ && !Component.render && !Component.ssrRender) {
417424
/* istanbul ignore if */
418425
if (!__RUNTIME_COMPILE__ && Component.template) {
419426
warn(
420427
`Component provides template but the build of Vue you are running ` +
421428
`does not support runtime template compilation. Either use the ` +
422429
`full build or pre-compile the template using Vue CLI.`
423430
)
424-
} else if (!__SSR__ || !Component.ssrRender) {
431+
} else {
425432
warn(
426433
`Component is missing${
427434
__RUNTIME_COMPILE__ ? ` template or` : ``

packages/runtime-core/src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,15 @@ import { createComponentInstance, setupComponent } from './component'
106106
import { renderComponentRoot } from './componentRenderUtils'
107107
import { normalizeVNode } from './vnode'
108108

109-
// SSR utils are only exposed in SSR builds.
109+
// SSR utils are only exposed in cjs builds.
110110
const _ssrUtils = {
111111
createComponentInstance,
112112
setupComponent,
113113
renderComponentRoot,
114114
normalizeVNode
115115
}
116116

117-
export const ssrUtils = (__SSR__ ? _ssrUtils : null) as typeof _ssrUtils
117+
export const ssrUtils = (__NODE_JS__ ? _ssrUtils : null) as typeof _ssrUtils
118118

119119
// Types -----------------------------------------------------------------------
120120

packages/server-renderer/src/renderToString.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ import {
1919
isPromise,
2020
isArray,
2121
isFunction,
22-
isVoidTag,
23-
EMPTY_OBJ
22+
isVoidTag
2423
} from '@vue/shared'
2524
import { renderProps } from './renderProps'
2625
import { escape } from './escape'
@@ -104,7 +103,11 @@ function renderComponentVNode(
104103
parentComponent: ComponentInternalInstance | null = null
105104
): ResolvedSSRBuffer | Promise<ResolvedSSRBuffer> {
106105
const instance = createComponentInstance(vnode, parentComponent)
107-
const res = setupComponent(instance, null)
106+
const res = setupComponent(
107+
instance,
108+
null /* parentSuspense */,
109+
true /* isSSR */
110+
)
108111
if (isPromise(res)) {
109112
return res.then(() => renderComponentSubTree(instance))
110113
} else {

rollup.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ function createReplacePlugin(
173173
// support compile in browser?
174174
__RUNTIME_COMPILE__: isRuntimeCompileBuild,
175175
// is targeting Node (SSR)?
176-
__SSR__: isNodeBuild,
176+
__NODE_JS__: isNodeBuild,
177177
// support options?
178178
// the lean build drops options related code with buildOptions.lean: true
179179
__FEATURE_OPTIONS__: !packageOptions.lean && !process.env.LEAN,

0 commit comments

Comments
 (0)