Skip to content

Commit

Permalink
fix($core): SSR error when async components were registered in runtime.
Browse files Browse the repository at this point in the history
  • Loading branch information
ulivz committed Sep 9, 2018
1 parent 6550f86 commit feb74eb
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
8 changes: 7 additions & 1 deletion packages/@vuepress/core/lib/app/components/Content.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ export default {

render (h, { parent, props, data }) {
const pageKey = props.pageKey || parent.$page.key

if (components[pageKey]) {
Vue.component(pageKey, components[pageKey])
// In SSR, if a component is not registered with the component option
// vue-server-renderer will not be able to resovle it.
if (!parent.$ssrContext) {
Vue.component(pageKey, components[pageKey])
}

return h(pageKey, {
class: [props.custom ? 'custom' : '', data.class, data.staticClass],
style: data.style,
Expand Down
26 changes: 25 additions & 1 deletion packages/@vuepress/core/lib/app/serverEntry.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Vue from 'vue'
import { createApp } from './app'
import pageComponents from '@internal/page-components'
import layoutComponents from '@internal/layout-components'

export default context => new Promise((resolve, reject) => {
const { app, router } = createApp(true /* isServer */)
Expand All @@ -10,5 +13,26 @@ export default context => new Promise((resolve, reject) => {
}

router.push(url)
router.onReady(() => resolve(app))

// In SSR, if a component is not registered with the component option,
// vue-server-renderer will not able to resolve it.
//
// Build also works after deleting this, but the content of all pages
// will not appear to the output html, which is not conducive to SEO.
const asyncComponentLoadingPromises = [
...getComponentArr(pageComponents),
...getComponentArr(layoutComponents)
].map(({ name, loadFn }) => {
return loadFn.then(comp => {
Vue.component(name, comp.default)
})
})

router.onReady(() => {
Promise.all(asyncComponentLoadingPromises).then(() => resolve(app))
})
})

function getComponentArr (components) {
return Object.keys(components).map(name => ({ name, loadFn: components[name] }))
}

0 comments on commit feb74eb

Please sign in to comment.