Skip to content

Commit

Permalink
fix(core): prefetch used components from nuxt-content (#377)
Browse files Browse the repository at this point in the history
* fix(core): prefetch used components from nuxt-content

* chore: add key for component
  • Loading branch information
atinux authored and Tahul committed Jun 7, 2021
1 parent c7e2c90 commit 1f72ba1
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/app/pages/_.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<Component :is="page.template" :page="page" />
<Component :is="page.template" :key="page.template" :page="page" />
</template>

<script>
Expand Down
4 changes: 3 additions & 1 deletion src/core/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export default async function (ctx, inject) {
inject('docus', $docus)

/* <% if (options.watch) { %> */
useWebSocket({ base: '<%= options.apiBase %>' }).connect()
if (process.client) {
useWebSocket({ base: '<%= options.apiBase %>' }).connect()
}
/* <% } %> */
}
26 changes: 20 additions & 6 deletions src/core/runtime/components/NuxtContent.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script>
import { pascalCase } from 'scule'
import Vue from 'vue'
import info from 'property-information'
const rootKeys = ['class-name', 'class', 'style']
Expand All @@ -8,6 +10,8 @@ const rxBind = /^:|^v-bind:/
const rxModel = /^v-model/
const nativeInputs = ['select', 'textarea', 'input']
const lazyComponents = new Set()
function evalInContext(code, context) {
// eslint-disable-next-line no-new-func
return new Function('with(this) { return (' + code + ') }').call(context)
Expand Down Expand Up @@ -115,6 +119,9 @@ function processNode(node, h, doc) {
children.push(...processQueue.map(node => processNode(node, h, doc)))
}
if (process.server && typeof Vue.component(pascalCase(node.tag)) === 'function') {
lazyComponents.add(pascalCase(node.tag))
}
return h(node.tag, data, children)
}
Expand Down Expand Up @@ -149,7 +156,7 @@ export default {
required: true
}
},
render(h, { data, props }) {
render(h, { data, props, parent }) {
const { document } = props
const { body } = document || {}
if (!body || !body.children || !Array.isArray(body.children)) {
Expand All @@ -166,11 +173,18 @@ export default {
}
data.class = classes.concat('nuxt-content')
data.props = Object.assign({ ...body.props }, data.props)
return h(
'div',
data,
body.children.map(child => processNode(child, h, document))
)
const children = body.children.map(child => processNode(child, h, document))
if (process.server) {
parent.$root.context.beforeSerialize(nuxtState => {
if (nuxtState.fetch._lazyComponents) {
lazyComponents.forEach(name => nuxtState.fetch._lazyComponents.add(name))
} else {
nuxtState.fetch._lazyComponents = lazyComponents
}
})
}
return h('div', data, children)
}
}
</script>
36 changes: 25 additions & 11 deletions src/core/runtime/composables/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,39 @@ export const docusInit = ({ context, state }: DocusAddonContext) => {
}
}

export const clientAsyncData = (app, $nuxt: any) => {
export const clientAsyncData = (_app, $nuxt: any) => {
if (process.client) {
const loadedComponents = new Set()
const loadComponents = function (components?: Set<string>) {
if (!components) return
return Array.from(components).map(async function (name) {
if (!loadedComponents.has(name) && typeof Vue.component(name) === 'function') {
loadedComponents.add(name)
try {
// @ts-ignore
await Vue.component(name)()
} catch (e) {}
}
})
}
window.onNuxtReady((nuxt: any) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
$nuxt = nuxt

// Workaround since in full static mode, asyncData is not called anymore
app.router.beforeEach((_: any, __: any, next: any) => {
const payload = nuxt._pagePayload || {}
// Workaround for Vue 2 since <Suspense> does not exists
const originalFetchPayload = $nuxt.fetchPayload
if (originalFetchPayload) {
$nuxt.fetchPayload = async function (...args) {
const payload = await originalFetchPayload(...args)

payload.data = payload.data || []
await loadComponents(payload.fetch?._lazyComponents)
await loadComponents(new Set(payload.data[0]?.page?.template))

if (payload.data[0]?.page?.template && typeof Vue.component(payload.data[0].page.template) === 'function') {
// Preload the component on client-side navigation
Vue.component(payload.data[0].page.template)
return payload
}

next()
})
}
// Fetch NuxtContent component
loadComponents(new Set('NuxtContent'))
})
}
}

0 comments on commit 1f72ba1

Please sign in to comment.