From: Evan You Date: Wed, 29 Jan 2020 14:49:17 +0000 (-0500) Subject: fix(ssr): avoid hard-coded ssr checks in cjs builds X-Git-Tag: v3.0.0-alpha.5~159 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bc07e95ca84686bfa43798a444a3220581b183d8;p=thirdparty%2Fvuejs%2Fcore.git fix(ssr): avoid hard-coded ssr checks in cjs builds --- diff --git a/jest.config.js b/jest.config.js index 48ded2ca42..46f235dc41 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,7 +7,7 @@ module.exports = { __BROWSER__: false, __BUNDLER__: true, __RUNTIME_COMPILE__: true, - __SSR__: false, + __NODE_JS__: true, __FEATURE_OPTIONS__: true, __FEATURE_SUSPENSE__: true }, diff --git a/packages/global.d.ts b/packages/global.d.ts index 5af13958e4..7d1805539c 100644 --- a/packages/global.d.ts +++ b/packages/global.d.ts @@ -4,7 +4,7 @@ declare var __TEST__: boolean declare var __BROWSER__: boolean declare var __BUNDLER__: boolean declare var __RUNTIME_COMPILE__: boolean -declare var __SSR__: boolean +declare var __NODE_JS__: boolean declare var __COMMIT__: string declare var __VERSION__: string diff --git a/packages/runtime-core/src/apiLifecycle.ts b/packages/runtime-core/src/apiLifecycle.ts index 0b0c25e2f9..8733ecd2bd 100644 --- a/packages/runtime-core/src/apiLifecycle.ts +++ b/packages/runtime-core/src/apiLifecycle.ts @@ -2,7 +2,8 @@ import { ComponentInternalInstance, LifecycleHooks, currentInstance, - setCurrentInstance + setCurrentInstance, + isInSSRComponentSetup } from './component' import { ComponentPublicInstance } from './componentProxy' import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling' @@ -66,7 +67,7 @@ export const createHook = any>( lifecycle: LifecycleHooks ) => (hook: T, target: ComponentInternalInstance | null = currentInstance) => // 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 onMounted = createHook(LifecycleHooks.MOUNTED) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 000f48edb1..74acbfd59f 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -21,7 +21,8 @@ import { currentInstance, ComponentInternalInstance, currentSuspense, - Data + Data, + isInSSRComponentSetup } from './component' import { ErrorCodes, @@ -86,8 +87,8 @@ export function watch( cbOrOptions?: WatchCallback | WatchOptions, options?: WatchOptions ): StopHandle { - if (__SSR__ && !(options && options.flush === 'sync')) { - // during SSR, non-sync watchers never fire. + if (isInSSRComponentSetup && !(options && options.flush === 'sync')) { + // component watchers during SSR are no-op return NOOP } else if (isFunction(cbOrOptions)) { // effect callback as 2nd argument - this is a source watcher diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 70971260f5..889c45d39b 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -269,19 +269,26 @@ export function validateComponentName(name: string, config: AppConfig) { } } +export let isInSSRComponentSetup = false + export function setupComponent( instance: ComponentInternalInstance, - parentSuspense: SuspenseBoundary | null + parentSuspense: SuspenseBoundary | null, + isSSR = false ) { + isInSSRComponentSetup = isSSR const propsOptions = instance.type.props const { props, children, shapeFlag } = instance.vnode resolveProps(instance, props, propsOptions) resolveSlots(instance, children) // setup stateful logic + let setupResult if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { - return setupStatefulComponent(instance, parentSuspense) + setupResult = setupStatefulComponent(instance, parentSuspense) } + isInSSRComponentSetup = false + return setupResult } function setupStatefulComponent( @@ -314,7 +321,7 @@ function setupStatefulComponent( // 2. create props proxy // the propsProxy is a reactive AND readonly proxy to the actual props. // it will be updated in resolveProps() on updates before render - const propsProxy = (instance.propsProxy = __SSR__ + const propsProxy = (instance.propsProxy = isInSSRComponentSetup ? instance.props : shallowReadonly(instance.props)) // 3. call setup() @@ -335,7 +342,7 @@ function setupStatefulComponent( currentSuspense = null if (isPromise(setupResult)) { - if (__SSR__) { + if (isInSSRComponentSetup) { // return the promise so server-renderer can wait on it return setupResult.then(resolvedResult => { handleSetupResult(instance, resolvedResult, parentSuspense) @@ -413,7 +420,7 @@ function finishComponentSetup( ;(Component.render as RenderFunction).isRuntimeCompiled = true } - if (__DEV__ && !Component.render) { + if (__DEV__ && !Component.render && !Component.ssrRender) { /* istanbul ignore if */ if (!__RUNTIME_COMPILE__ && Component.template) { warn( @@ -421,7 +428,7 @@ function finishComponentSetup( `does not support runtime template compilation. Either use the ` + `full build or pre-compile the template using Vue CLI.` ) - } else if (!__SSR__ || !Component.ssrRender) { + } else { warn( `Component is missing${ __RUNTIME_COMPILE__ ? ` template or` : `` diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 9d82189359..12267adb0a 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -106,7 +106,7 @@ import { createComponentInstance, setupComponent } from './component' import { renderComponentRoot } from './componentRenderUtils' import { normalizeVNode } from './vnode' -// SSR utils are only exposed in SSR builds. +// SSR utils are only exposed in cjs builds. const _ssrUtils = { createComponentInstance, setupComponent, @@ -114,7 +114,7 @@ const _ssrUtils = { normalizeVNode } -export const ssrUtils = (__SSR__ ? _ssrUtils : null) as typeof _ssrUtils +export const ssrUtils = (__NODE_JS__ ? _ssrUtils : null) as typeof _ssrUtils // Types ----------------------------------------------------------------------- diff --git a/packages/server-renderer/src/renderToString.ts b/packages/server-renderer/src/renderToString.ts index ff3e2749cc..291593aa50 100644 --- a/packages/server-renderer/src/renderToString.ts +++ b/packages/server-renderer/src/renderToString.ts @@ -19,8 +19,7 @@ import { isPromise, isArray, isFunction, - isVoidTag, - EMPTY_OBJ + isVoidTag } from '@vue/shared' import { renderProps } from './renderProps' import { escape } from './escape' @@ -104,7 +103,11 @@ function renderComponentVNode( parentComponent: ComponentInternalInstance | null = null ): ResolvedSSRBuffer | Promise { const instance = createComponentInstance(vnode, parentComponent) - const res = setupComponent(instance, null) + const res = setupComponent( + instance, + null /* parentSuspense */, + true /* isSSR */ + ) if (isPromise(res)) { return res.then(() => renderComponentSubTree(instance)) } else { diff --git a/rollup.config.js b/rollup.config.js index bad7672a82..5d528bf904 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -173,7 +173,7 @@ function createReplacePlugin( // support compile in browser? __RUNTIME_COMPILE__: isRuntimeCompileBuild, // is targeting Node (SSR)? - __SSR__: isNodeBuild, + __NODE_JS__: isNodeBuild, // support options? // the lean build drops options related code with buildOptions.lean: true __FEATURE_OPTIONS__: !packageOptions.lean && !process.env.LEAN,