wip(ssr): initial work on server-renderer

This commit is contained in:
Evan You
2020-01-23 21:01:56 -05:00
parent c07751fd36
commit da25517377
8 changed files with 110 additions and 23 deletions

View File

@@ -19,8 +19,11 @@ export interface App<HostElement = any> {
mount(rootContainer: HostElement | string): ComponentPublicInstance
unmount(rootContainer: HostElement | string): void
provide<T>(key: InjectionKey<T> | string, value: T): this
rootComponent: Component
rootContainer: HostElement | null
// internal. We need to expose these for the server-renderer
_component: Component
_props: Data | null
_container: HostElement | null
}
export interface AppConfig {
@@ -85,18 +88,21 @@ export type CreateAppFunction<HostElement> = (
export function createAppAPI<HostNode, HostElement>(
render: RootRenderFunction<HostNode, HostElement>
): CreateAppFunction<HostElement> {
return function createApp(
rootComponent: Component,
rootProps?: Data | null
): App {
return function createApp(rootComponent: Component, rootProps = null) {
if (rootProps != null && !isObject(rootProps)) {
__DEV__ && warn(`root props passed to app.mount() must be an object.`)
rootProps = null
}
const context = createAppContext()
const installedPlugins = new Set()
let isMounted = false
const app: App = {
rootComponent,
rootContainer: null,
_component: rootComponent,
_props: rootProps,
_container: null,
get config() {
return context.config
@@ -176,11 +182,6 @@ export function createAppAPI<HostNode, HostElement>(
mount(rootContainer: HostElement): any {
if (!isMounted) {
if (rootProps != null && !isObject(rootProps)) {
__DEV__ &&
warn(`root props passed to app.mount() must be an object.`)
rootProps = null
}
const vnode = createVNode(rootComponent, rootProps)
// store app context on the root VNode.
// this will be set on the root instance on initial mount.
@@ -195,7 +196,7 @@ export function createAppAPI<HostNode, HostElement>(
render(vnode, rootContainer)
isMounted = true
app.rootContainer = rootContainer
app._container = rootContainer
return vnode.component!.proxy
} else if (__DEV__) {
warn(
@@ -206,7 +207,7 @@ export function createAppAPI<HostNode, HostElement>(
unmount() {
if (isMounted) {
render(null, app.rootContainer!)
render(null, app._container!)
} else if (__DEV__) {
warn(`Cannot unmount an app that is not mounted.`)
}

View File

@@ -63,6 +63,8 @@ export interface ComponentOptionsBase<
// Luckily `render()` doesn't need any arguments nor does it care about return
// type.
render?: Function
// SSR only. This is produced by compiler-ssr and attached in compiler-sfc
ssrRender?: Function
components?: Record<
string,
Component | { new (): ComponentPublicInstance<any, any, any, any, any> }

View File

@@ -154,7 +154,7 @@ export interface ComponentInternalInstance {
const emptyAppContext = createAppContext()
export function defineComponentInstance(
export function createComponentInstance(
vnode: VNode,
parent: ComponentInternalInstance | null
) {

View File

@@ -85,7 +85,7 @@ type NormalizedProp =
type NormalizedPropsOptions = [Record<string, NormalizedProp>, string[]]
// resolve raw VNode data.
// - filter out reserved keys (key, ref, slots)
// - filter out reserved keys (key, ref)
// - extract class and style into $attrs (to be merged onto child
// component root)
// - for the rest:

View File

@@ -12,7 +12,7 @@ import {
} from './vnode'
import {
ComponentInternalInstance,
defineComponentInstance,
createComponentInstance,
setupStatefulComponent,
Component,
Data
@@ -927,7 +927,7 @@ export function createRenderer<
parentSuspense: HostSuspenseBoundary | null,
isSVG: boolean
) {
const instance: ComponentInternalInstance = (initialVNode.component = defineComponentInstance(
const instance: ComponentInternalInstance = (initialVNode.component = createComponentInstance(
initialVNode,
parentComponent
))