cubic-ui
Version:
UI node for Cubic.
63 lines (49 loc) • 2.63 kB
JavaScript
import { createApp } from './app.js'
import { callAsyncRecursive } from './ssr/callAsyncRecursive.js'
import { registerStoreModules } from './ssr/registerStoreModules.js'
import root from 'src/app.vue'
/**
* Generate App with pre-fetched data in store state
*/
export default function (context) {
return new Promise((resolve, reject) => {
const { app, router, store } = createApp(context)
// Init vue-meta
const meta = app.$meta()
// Set router's location
router.push(context.req.url)
// Wait until router has resolved possible async hooks
router.onReady(async () => {
const routerView = router.getMatchedComponents()
// Register all dynamic store modules in components first since asyncData
// functions will likely depend on them. This also avoids the necessity to
// load dependencies first if they're already present in the template.
// router-view doesn't contain root template, so we call it additionally
registerStoreModules(root, store)
routerView.map(component => registerStoreModules(component, store))
// Call asyncData hooks on components matched by the route recursively.
// A asyncData hook dispatches a store action and returns a Promise,
// which is resolved when the action is complete and store state has been
// updated.
// router-view doesn't contain root template, so we call it additionally
await callAsyncRecursive(root, store, router)
await Promise.all(routerView.map(component => callAsyncRecursive(component, store, router, router.currentRoute)))
// Check if error was received
if (context.req.errorData) store.state.errorData = context.req.errorData
// After all asyncData hooks are resolved, our store is now
// filled with the state needed to render the app.
// Expose the state on the render context, and let the request handler
// inline the state in the HTML response. This allows the client-side
// store to pick-up the server-side state without having to duplicate
// the initial data fetching on the client.
context.state = store.state
// Give access token to state so the client can use it
if (context.req.access_token) context.state.$access_token = context.req.access_token
if (context.req.refresh_token) context.state.$refresh_token = context.req.refresh_token
context.state.$user = context.req.user
// Finally, add meta tags to context for injection in renderer
context.meta = { inject: function () { Object.assign(this, meta.inject()) } }
resolve(app)
})
})
}