From 4091b3308a9e9f438efe3fec4139f26fe2a4727c Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Fri, 7 Sep 2018 21:56:10 +0200 Subject: [PATCH] refactor: move fake instance creation to utils file --- ssr/index.js | 143 +----------------------------------------------- ssr/utils.js | 149 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 144 deletions(-) diff --git a/ssr/index.js b/ssr/index.js index d851281..75bcada 100644 --- a/ssr/index.js +++ b/ssr/index.js @@ -1,12 +1,7 @@ const chalk = require('chalk') const { VUE_APOLLO_QUERY_KEYWORDS } = require('../lib/consts') -const { VM_HELPERS, SSR_HELPERS, COMPONENT_BLACKLIST } = require('./consts') -const { resolveAsset, defineComputed } = require('./utils') -const { Globals, getMergedDefinition, omit, noop } = require('../lib/utils') - -function emptyString () { - return '' -} +const { createFakeInstance, resolveComponent } = require('./utils') +const { Globals, getMergedDefinition, omit } = require('../lib/utils') exports.install = function (Vue) { Globals.Vue = Vue @@ -99,140 +94,6 @@ function prefetchComponent (component, vm, queries) { } } -function createFakeInstance (options, data, parent, children, context) { - const vm = Object.assign( - {}, - data.attrs, - data.props, - { - $prefetch: true, - $parent: parent, - $children: children, - $attrs: data.attrs, - $props: data.props, - $slots: {}, - $scopedSlots: {}, - $set: Globals.Vue.set, - $delete: Globals.Vue.delete, - $route: context.route, - $store: context.store, - $apollo: { - queries: {}, - loading: false, - }, - $apolloData: { - loading: false, - }, - _self: {}, - _staticTrees: [], - _u: resolveScopedSlots, - } - ) - - // Render and other helpers - VM_HELPERS.forEach(helper => vm[helper] = noop) - SSR_HELPERS.forEach(helper => vm[helper] = emptyString) - - // Scoped slots - if (data.scopedSlots) { - vm.$scopedSlots = data.scopedSlots - } - - // Route props - if (context && context.route) { - const { route } = context - const matchedRoute = findRouteMatch(options, route) - if (matchedRoute && matchedRoute.props) { - const { props } = matchedRoute - if (props === true) { - Object.assign(vm, matchedRoute.params) - } else if (typeof props === 'function') { - Object.assign(vm, props(matchedRoute)) - } else if (typeof props === 'object') { - Object.assign(vm, props) - } - } - } - - // Methods - const methods = options.methods - for (const key in methods) { - vm[key] = methods[key].bind(vm) - } - - // Computed - const computed = options.computed - for (const key in computed) { - defineComputed(vm, key, computed[key]) - } - - // Data - const localData = options.data - if (typeof localData === 'function') { - vm._data = localData.call(vm, vm) - } else if (typeof localData === 'object') { - vm._data = localData - } else { - vm._data = {} - } - vm.$data = vm._data - Object.assign(vm, vm._data) - - // Prefetch state - const prefetch = options.prefetch - if (typeof prefetch === 'function') { - Object.assign(vm, prefetch(context)) - } else if (typeof prefetch === 'object') { - Object.assign(vm, prefetch) - } - - return vm -} - -function findRouteMatch (component, route) { - for (const r of route.matched) { - for (const key in r.components) { - if (r.components[key] === component) { - return r - } - } - } -} - -function resolveComponent (name, options) { - return new Promise((resolve) => { - if (options.components) { - const component = resolveAsset(options.components, name) - if (component !== undefined) { - resolve(component) - } - } - return resolve(Globals.Vue.options.components[name]) - }).then(component => { - if (component) { - component = getMergedDefinition(component) - if (!component.functional && ( - !component.name || - !COMPONENT_BLACKLIST.includes(component.name) - )) { - return component - } - } - }) -} - -function resolveScopedSlots (fns, res) { - res = res || {} - for (var i = 0; i < fns.length; i++) { - if (Array.isArray(fns[i])) { - resolveScopedSlots(fns[i], res) - } else { - res[fns[i].key] = fns[i].fn - } - } - return res -} - function prefetchQuery (apolloProvider, query, context) { try { let variables diff --git a/ssr/utils.js b/ssr/utils.js index 03afdb2..80ab362 100644 --- a/ssr/utils.js +++ b/ssr/utils.js @@ -1,4 +1,11 @@ -const { noop } = require('../lib/utils') +const { VM_HELPERS, SSR_HELPERS, COMPONENT_BLACKLIST } = require('./consts') +const { Globals, getMergedDefinition, noop } = require('../lib/utils') + +/* Fake instance creation */ + +function emptyString () { + return '' +} const computedPropDef = { enumerable: true, @@ -7,7 +14,7 @@ const computedPropDef = { set: noop, } -exports.defineComputed = function (target, key, userDef) { +function defineComputed (target, key, userDef) { if (typeof userDef === 'function') { computedPropDef.get = userDef computedPropDef.set = noop @@ -18,6 +25,120 @@ exports.defineComputed = function (target, key, userDef) { Object.defineProperty(target, key, computedPropDef) } +function resolveScopedSlots (fns, res) { + res = res || {} + for (var i = 0; i < fns.length; i++) { + if (Array.isArray(fns[i])) { + resolveScopedSlots(fns[i], res) + } else { + res[fns[i].key] = fns[i].fn + } + } + return res +} + +function findRouteMatch (component, route) { + for (const r of route.matched) { + for (const key in r.components) { + if (r.components[key] === component) { + return r + } + } + } +} + +exports.createFakeInstance = function (options, data, parent, children, context) { + const vm = Object.assign( + {}, + data.attrs, + data.props, + { + $prefetch: true, + $parent: parent, + $children: children, + $attrs: data.attrs, + $props: data.props, + $slots: {}, + $scopedSlots: {}, + $set: Globals.Vue.set, + $delete: Globals.Vue.delete, + $route: context.route, + $store: context.store, + $apollo: { + queries: {}, + loading: false, + }, + $apolloData: { + loading: false, + }, + _self: {}, + _staticTrees: [], + _u: resolveScopedSlots, + } + ) + + // Render and other helpers + VM_HELPERS.forEach(helper => vm[helper] = noop) + SSR_HELPERS.forEach(helper => vm[helper] = emptyString) + + // Scoped slots + if (data.scopedSlots) { + vm.$scopedSlots = data.scopedSlots + } + + // Route props + if (context && context.route) { + const { route } = context + const matchedRoute = findRouteMatch(options, route) + if (matchedRoute && matchedRoute.props) { + const { props } = matchedRoute + if (props === true) { + Object.assign(vm, matchedRoute.params) + } else if (typeof props === 'function') { + Object.assign(vm, props(matchedRoute)) + } else if (typeof props === 'object') { + Object.assign(vm, props) + } + } + } + + // Methods + const methods = options.methods + for (const key in methods) { + vm[key] = methods[key].bind(vm) + } + + // Computed + const computed = options.computed + for (const key in computed) { + defineComputed(vm, key, computed[key]) + } + + // Data + const localData = options.data + if (typeof localData === 'function') { + vm._data = localData.call(vm, vm) + } else if (typeof localData === 'object') { + vm._data = localData + } else { + vm._data = {} + } + vm.$data = vm._data + Object.assign(vm, vm._data) + + // Prefetch state + const prefetch = options.prefetch + if (typeof prefetch === 'function') { + Object.assign(vm, prefetch(context)) + } else if (typeof prefetch === 'object') { + Object.assign(vm, prefetch) + } + + return vm +} + +/* Component resolution */ + function cached (fn) { const cache = Object.create(null) return function cachedFn (str) { @@ -40,7 +161,7 @@ function hasOwn (obj, key) { return hasOwnProperty.call(obj, key) } -exports.resolveAsset = function (assets, id) { +function resolveAsset (assets, id) { if (typeof id !== 'string') return if (hasOwn(assets, id)) return assets[id] @@ -51,3 +172,25 @@ exports.resolveAsset = function (assets, id) { const pascalCaseId = capitalize(camelCaseId) if (hasOwn(assets, pascalCaseId)) return assets[pascalCaseId] } + +exports.resolveComponent = function (name, options) { + return new Promise((resolve) => { + if (options.components) { + const component = resolveAsset(options.components, name) + if (component !== undefined) { + resolve(component) + } + } + return resolve(Globals.Vue.options.components[name]) + }).then(component => { + if (component) { + component = getMergedDefinition(component) + if (!component.functional && ( + !component.name || + !COMPONENT_BLACKLIST.includes(component.name) + )) { + return component + } + } + }) +}