]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip(ssr): render real components
authorEvan You <yyx990803@gmail.com>
Fri, 24 Jan 2020 03:23:10 +0000 (22:23 -0500)
committerEvan You <yyx990803@gmail.com>
Mon, 27 Jan 2020 21:00:17 +0000 (16:00 -0500)
jest.config.js
packages/global.d.ts
packages/runtime-core/src/component.ts
packages/runtime-core/src/index.ts
packages/runtime-core/src/renderer.ts
packages/server-renderer/package.json
packages/server-renderer/src/index.ts
rollup.config.js

index 748bed519d3a5e4574586f63392e4a3d1225e357..48ded2ca42d2432a7934b14ed728f92dc4e83f01 100644 (file)
@@ -7,6 +7,7 @@ module.exports = {
     __BROWSER__: false,
     __BUNDLER__: true,
     __RUNTIME_COMPILE__: true,
+    __SSR__: false,
     __FEATURE_OPTIONS__: true,
     __FEATURE_SUSPENSE__: true
   },
index cfe02b96a681e30f2b37641a5cba5d473040a2a1..5af13958e441c91efeb197d85a789da0c3cc1060 100644 (file)
@@ -4,6 +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 __COMMIT__: string
 declare var __VERSION__: string
 
index fb0f3d68d3c73d19ef1dd95122fabf95f678995a..77f7678737427f0071cdb9d844ba1cc004970621 100644 (file)
@@ -5,8 +5,8 @@ import {
   ComponentPublicInstance,
   runtimeCompiledRenderProxyHandlers
 } from './componentProxy'
-import { ComponentPropsOptions } from './componentProps'
-import { Slots } from './componentSlots'
+import { ComponentPropsOptions, resolveProps } from './componentProps'
+import { Slots, resolveSlots } from './componentSlots'
 import { warn } from './warning'
 import {
   ErrorCodes,
@@ -34,6 +34,7 @@ import {
   currentRenderingInstance,
   markAttrsAccessed
 } from './componentRenderUtils'
+import { ShapeFlags } from '.'
 
 export type Data = { [key: string]: unknown }
 
@@ -268,10 +269,26 @@ export function validateComponentName(name: string, config: AppConfig) {
   }
 }
 
-export function setupStatefulComponent(
+export function setupComponent(
   instance: ComponentInternalInstance,
   parentSuspense: SuspenseBoundary | null
 ) {
+  const propsOptions = instance.type.props
+  const { props, children, shapeFlag } = instance.vnode
+  resolveProps(instance, props, propsOptions)
+  resolveSlots(instance, children)
+
+  // setup stateful logic
+  if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
+    return setupStatefulComponent(instance, parentSuspense)
+  }
+}
+
+function setupStatefulComponent(
+  instance: ComponentInternalInstance,
+  parentSuspense: SuspenseBoundary | null
+) {
+  let setupResult
   const Component = instance.type as ComponentOptions
 
   if (__DEV__) {
@@ -307,7 +324,7 @@ export function setupStatefulComponent(
 
     currentInstance = instance
     currentSuspense = parentSuspense
-    const setupResult = callWithErrorHandling(
+    setupResult = callWithErrorHandling(
       setup,
       instance,
       ErrorCodes.SETUP_FUNCTION,
@@ -333,6 +350,8 @@ export function setupStatefulComponent(
   } else {
     finishComponentSetup(instance, parentSuspense)
   }
+
+  return setupResult
 }
 
 export function handleSetupResult(
@@ -398,7 +417,7 @@ function finishComponentSetup(
             `does not support runtime template compilation. Either use the ` +
             `full build or pre-compile the template using Vue CLI.`
         )
-      } else {
+      } else if (!__SSR__ || !Component.ssrRender) {
         warn(
           `Component is missing${
             __RUNTIME_COMPILE__ ? ` template or` : ``
index 435ede78176dfba6591e839acd6d0014a870afb6..2976c53a1ebc478ae0f5e4b55d4033da693fbc26 100644 (file)
@@ -97,6 +97,9 @@ export const camelize = _camelize as (s: string) => string
 // For integration with runtime compiler
 export { registerRuntimeCompiler } from './component'
 
+// For server-renderer
+export { createComponentInstance, setupComponent } from './component'
+
 // Types -----------------------------------------------------------------------
 
 export {
index 2fb27c41a547f91b0c69d4771399ed78068ef339..fc208d8cc8c290df14952b334d20092a1eab67fe 100644 (file)
@@ -13,9 +13,9 @@ import {
 import {
   ComponentInternalInstance,
   createComponentInstance,
-  setupStatefulComponent,
   Component,
-  Data
+  Data,
+  setupComponent
 } from './component'
 import {
   renderComponentRoot,
@@ -940,8 +940,6 @@ export function createRenderer<
       pushWarningContext(initialVNode)
     }
 
-    const Comp = initialVNode.type as Component
-
     // inject renderer internals for keepAlive
     if (isKeepAlive(initialVNode)) {
       const sink = instance.sink as KeepAliveSink
@@ -950,14 +948,7 @@ export function createRenderer<
     }
 
     // resolve props and slots for setup context
-    const propsOptions = Comp.props
-    resolveProps(instance, initialVNode.props, propsOptions)
-    resolveSlots(instance, initialVNode.children)
-
-    // setup stateful logic
-    if (initialVNode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
-      setupStatefulComponent(instance, parentSuspense)
-    }
+    setupComponent(instance, parentSuspense)
 
     // setup() is async. This component relies on async logic to be resolved
     // before proceeding
index 0e8743b4f6829583cca8878fa12d54bfd35d5106..038dae62a24f282d4c7eee6431a2a56a431c7d4c 100644 (file)
@@ -27,6 +27,6 @@
   },
   "homepage": "https://github.com/vuejs/vue/tree/dev/packages/server-renderer#readme",
   "peerDependencies": {
-    "@vue/runtime-dom": "3.0.0-alpha.3"
+    "vue": "3.0.0-alpha.3"
   }
 }
index 17c5f9beab6b2762cb181acf6a2826f5f0dee76e..e78099a6703065347304c6df468b83b3f3308081 100644 (file)
@@ -2,8 +2,11 @@ import {
   App,
   Component,
   ComponentInternalInstance,
-  SuspenseBoundary
-} from '@vue/runtime-dom'
+  createComponentInstance,
+  setupComponent,
+  VNode,
+  createVNode
+} from 'vue'
 import { isString } from '@vue/shared'
 
 type SSRBuffer = SSRBufferItem[]
@@ -30,9 +33,7 @@ function createSSRBuffer() {
 export async function renderToString(app: App): Promise<string> {
   const resolvedBuffer = (await renderComponent(
     app._component,
-    app._props,
-    null,
-    null
+    app._props
   )) as ResolvedSSRBuffer
   return unrollBuffer(resolvedBuffer)
 }
@@ -52,19 +53,17 @@ function unrollBuffer(buffer: ResolvedSSRBuffer): string {
 
 export async function renderComponent(
   comp: Component,
-  props: Record<string, any> | null,
-  parentComponent: ComponentInternalInstance | null,
-  parentSuspense: SuspenseBoundary | null
+  props: Record<string, any> | null = null,
+  children: VNode['children'] = null,
+  parentComponent: ComponentInternalInstance | null = null
 ): Promise<SSRBuffer> {
   // 1. create component buffer
   const { buffer, push } = createSSRBuffer()
 
-  // 2. TODO create actual instance
-  const instance = {
-    proxy: {
-      msg: 'hello'
-    }
-  }
+  // 2. create actual instance
+  const vnode = createVNode(comp, props, children)
+  const instance = createComponentInstance(vnode, parentComponent)
+  await setupComponent(instance, null)
 
   if (typeof comp === 'function') {
     // TODO FunctionalComponent
index 0604dff9b2f3844a9d87a5cc94ab32e01a71ad5d..29ead12fa6eab0132e82be4ebe8e0d99637c607c 100644 (file)
@@ -79,6 +79,7 @@ function createConfig(format, output, plugins = []) {
     process.env.__DEV__ === 'false' || /\.prod\.js$/.test(output.file)
   const isGlobalBuild = format === 'global'
   const isRawESMBuild = format === 'esm'
+  const isNodeBuild = format === 'cjs'
   const isBundlerESMBuild = /esm-bundler/.test(format)
   const isRuntimeCompileBuild = /vue\./.test(output.file)
 
@@ -111,14 +112,16 @@ function createConfig(format, output, plugins = []) {
   const entryFile =
     format === 'esm-bundler-runtime' ? `src/runtime.ts` : `src/index.ts`
 
+  const external =
+    isGlobalBuild || isRawESMBuild
+      ? []
+      : knownExternals.concat(Object.keys(pkg.dependencies || []))
+
   return {
     input: resolve(entryFile),
     // Global and Browser ESM builds inlines everything so that they can be
     // used alone.
-    external:
-      isGlobalBuild || isRawESMBuild
-        ? []
-        : knownExternals.concat(Object.keys(pkg.dependencies || [])),
+    external,
     plugins: [
       json({
         namedExports: false
@@ -127,9 +130,11 @@ function createConfig(format, output, plugins = []) {
       createReplacePlugin(
         isProductionBuild,
         isBundlerESMBuild,
+        // isBrowserBuild?
         (isGlobalBuild || isRawESMBuild || isBundlerESMBuild) &&
           !packageOptions.enableNonBrowserBranches,
-        isRuntimeCompileBuild
+        isRuntimeCompileBuild,
+        isNodeBuild
       ),
       ...plugins
     ],
@@ -146,7 +151,8 @@ function createReplacePlugin(
   isProduction,
   isBundlerESMBuild,
   isBrowserBuild,
-  isRuntimeCompileBuild
+  isRuntimeCompileBuild,
+  isNodeBuild
 ) {
   const replacements = {
     __COMMIT__: `"${process.env.COMMIT}"`,
@@ -164,6 +170,8 @@ function createReplacePlugin(
     __BUNDLER__: isBundlerESMBuild,
     // support compile in browser?
     __RUNTIME_COMPILE__: isRuntimeCompileBuild,
+    // is targeting Node (SSR)?
+    __SSR__: isNodeBuild,
     // support options?
     // the lean build drops options related code with buildOptions.lean: true
     __FEATURE_OPTIONS__: !packageOptions.lean && !process.env.LEAN,