fix(ssr): avoid hard-coded ssr checks in cjs builds

This commit is contained in:
Evan You 2020-01-29 09:49:17 -05:00
parent 6b1ce00621
commit bc07e95ca8
8 changed files with 31 additions and 19 deletions

View File

@ -7,7 +7,7 @@ module.exports = {
__BROWSER__: false, __BROWSER__: false,
__BUNDLER__: true, __BUNDLER__: true,
__RUNTIME_COMPILE__: true, __RUNTIME_COMPILE__: true,
__SSR__: false, __NODE_JS__: true,
__FEATURE_OPTIONS__: true, __FEATURE_OPTIONS__: true,
__FEATURE_SUSPENSE__: true __FEATURE_SUSPENSE__: true
}, },

View File

@ -4,7 +4,7 @@ declare var __TEST__: boolean
declare var __BROWSER__: boolean declare var __BROWSER__: boolean
declare var __BUNDLER__: boolean declare var __BUNDLER__: boolean
declare var __RUNTIME_COMPILE__: boolean declare var __RUNTIME_COMPILE__: boolean
declare var __SSR__: boolean declare var __NODE_JS__: boolean
declare var __COMMIT__: string declare var __COMMIT__: string
declare var __VERSION__: string declare var __VERSION__: string

View File

@ -2,7 +2,8 @@ import {
ComponentInternalInstance, ComponentInternalInstance,
LifecycleHooks, LifecycleHooks,
currentInstance, currentInstance,
setCurrentInstance setCurrentInstance,
isInSSRComponentSetup
} from './component' } from './component'
import { ComponentPublicInstance } from './componentProxy' import { ComponentPublicInstance } from './componentProxy'
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling' import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
@ -66,7 +67,7 @@ export const createHook = <T extends Function = () => any>(
lifecycle: LifecycleHooks lifecycle: LifecycleHooks
) => (hook: T, target: ComponentInternalInstance | null = currentInstance) => ) => (hook: T, target: ComponentInternalInstance | null = currentInstance) =>
// post-create lifecycle registrations are noops during SSR // post-create lifecycle registrations are noops during SSR
!__SSR__ && injectHook(lifecycle, hook, target) !isInSSRComponentSetup && injectHook(lifecycle, hook, target)
export const onBeforeMount = createHook(LifecycleHooks.BEFORE_MOUNT) export const onBeforeMount = createHook(LifecycleHooks.BEFORE_MOUNT)
export const onMounted = createHook(LifecycleHooks.MOUNTED) export const onMounted = createHook(LifecycleHooks.MOUNTED)

View File

@ -21,7 +21,8 @@ import {
currentInstance, currentInstance,
ComponentInternalInstance, ComponentInternalInstance,
currentSuspense, currentSuspense,
Data Data,
isInSSRComponentSetup
} from './component' } from './component'
import { import {
ErrorCodes, ErrorCodes,
@ -86,8 +87,8 @@ export function watch<T = any>(
cbOrOptions?: WatchCallback<T> | WatchOptions, cbOrOptions?: WatchCallback<T> | WatchOptions,
options?: WatchOptions options?: WatchOptions
): StopHandle { ): StopHandle {
if (__SSR__ && !(options && options.flush === 'sync')) { if (isInSSRComponentSetup && !(options && options.flush === 'sync')) {
// during SSR, non-sync watchers never fire. // component watchers during SSR are no-op
return NOOP return NOOP
} else if (isFunction(cbOrOptions)) { } else if (isFunction(cbOrOptions)) {
// effect callback as 2nd argument - this is a source watcher // effect callback as 2nd argument - this is a source watcher

View File

@ -269,19 +269,26 @@ export function validateComponentName(name: string, config: AppConfig) {
} }
} }
export let isInSSRComponentSetup = false
export function setupComponent( export function setupComponent(
instance: ComponentInternalInstance, instance: ComponentInternalInstance,
parentSuspense: SuspenseBoundary | null parentSuspense: SuspenseBoundary | null,
isSSR = false
) { ) {
isInSSRComponentSetup = isSSR
const propsOptions = instance.type.props const propsOptions = instance.type.props
const { props, children, shapeFlag } = instance.vnode const { props, children, shapeFlag } = instance.vnode
resolveProps(instance, props, propsOptions) resolveProps(instance, props, propsOptions)
resolveSlots(instance, children) resolveSlots(instance, children)
// setup stateful logic // setup stateful logic
let setupResult
if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
return setupStatefulComponent(instance, parentSuspense) setupResult = setupStatefulComponent(instance, parentSuspense)
} }
isInSSRComponentSetup = false
return setupResult
} }
function setupStatefulComponent( function setupStatefulComponent(
@ -314,7 +321,7 @@ function setupStatefulComponent(
// 2. create props proxy // 2. create props proxy
// the propsProxy is a reactive AND readonly proxy to the actual props. // the propsProxy is a reactive AND readonly proxy to the actual props.
// it will be updated in resolveProps() on updates before render // it will be updated in resolveProps() on updates before render
const propsProxy = (instance.propsProxy = __SSR__ const propsProxy = (instance.propsProxy = isInSSRComponentSetup
? instance.props ? instance.props
: shallowReadonly(instance.props)) : shallowReadonly(instance.props))
// 3. call setup() // 3. call setup()
@ -335,7 +342,7 @@ function setupStatefulComponent(
currentSuspense = null currentSuspense = null
if (isPromise(setupResult)) { if (isPromise(setupResult)) {
if (__SSR__) { if (isInSSRComponentSetup) {
// return the promise so server-renderer can wait on it // return the promise so server-renderer can wait on it
return setupResult.then(resolvedResult => { return setupResult.then(resolvedResult => {
handleSetupResult(instance, resolvedResult, parentSuspense) handleSetupResult(instance, resolvedResult, parentSuspense)
@ -413,7 +420,7 @@ function finishComponentSetup(
;(Component.render as RenderFunction).isRuntimeCompiled = true ;(Component.render as RenderFunction).isRuntimeCompiled = true
} }
if (__DEV__ && !Component.render) { if (__DEV__ && !Component.render && !Component.ssrRender) {
/* istanbul ignore if */ /* istanbul ignore if */
if (!__RUNTIME_COMPILE__ && Component.template) { if (!__RUNTIME_COMPILE__ && Component.template) {
warn( warn(
@ -421,7 +428,7 @@ function finishComponentSetup(
`does not support runtime template compilation. Either use the ` + `does not support runtime template compilation. Either use the ` +
`full build or pre-compile the template using Vue CLI.` `full build or pre-compile the template using Vue CLI.`
) )
} else if (!__SSR__ || !Component.ssrRender) { } else {
warn( warn(
`Component is missing${ `Component is missing${
__RUNTIME_COMPILE__ ? ` template or` : `` __RUNTIME_COMPILE__ ? ` template or` : ``

View File

@ -106,7 +106,7 @@ import { createComponentInstance, setupComponent } from './component'
import { renderComponentRoot } from './componentRenderUtils' import { renderComponentRoot } from './componentRenderUtils'
import { normalizeVNode } from './vnode' import { normalizeVNode } from './vnode'
// SSR utils are only exposed in SSR builds. // SSR utils are only exposed in cjs builds.
const _ssrUtils = { const _ssrUtils = {
createComponentInstance, createComponentInstance,
setupComponent, setupComponent,
@ -114,7 +114,7 @@ const _ssrUtils = {
normalizeVNode normalizeVNode
} }
export const ssrUtils = (__SSR__ ? _ssrUtils : null) as typeof _ssrUtils export const ssrUtils = (__NODE_JS__ ? _ssrUtils : null) as typeof _ssrUtils
// Types ----------------------------------------------------------------------- // Types -----------------------------------------------------------------------

View File

@ -19,8 +19,7 @@ import {
isPromise, isPromise,
isArray, isArray,
isFunction, isFunction,
isVoidTag, isVoidTag
EMPTY_OBJ
} from '@vue/shared' } from '@vue/shared'
import { renderProps } from './renderProps' import { renderProps } from './renderProps'
import { escape } from './escape' import { escape } from './escape'
@ -104,7 +103,11 @@ function renderComponentVNode(
parentComponent: ComponentInternalInstance | null = null parentComponent: ComponentInternalInstance | null = null
): ResolvedSSRBuffer | Promise<ResolvedSSRBuffer> { ): ResolvedSSRBuffer | Promise<ResolvedSSRBuffer> {
const instance = createComponentInstance(vnode, parentComponent) const instance = createComponentInstance(vnode, parentComponent)
const res = setupComponent(instance, null) const res = setupComponent(
instance,
null /* parentSuspense */,
true /* isSSR */
)
if (isPromise(res)) { if (isPromise(res)) {
return res.then(() => renderComponentSubTree(instance)) return res.then(() => renderComponentSubTree(instance))
} else { } else {

View File

@ -173,7 +173,7 @@ function createReplacePlugin(
// support compile in browser? // support compile in browser?
__RUNTIME_COMPILE__: isRuntimeCompileBuild, __RUNTIME_COMPILE__: isRuntimeCompileBuild,
// is targeting Node (SSR)? // is targeting Node (SSR)?
__SSR__: isNodeBuild, __NODE_JS__: isNodeBuild,
// support options? // support options?
// the lean build drops options related code with buildOptions.lean: true // the lean build drops options related code with buildOptions.lean: true
__FEATURE_OPTIONS__: !packageOptions.lean && !process.env.LEAN, __FEATURE_OPTIONS__: !packageOptions.lean && !process.env.LEAN,