UNPKG

2.64 kBJavaScriptView Raw
1import { createApp } from './app.js'
2import { callAsyncRecursive } from './ssr/callAsyncRecursive.js'
3import { registerStoreModules } from './ssr/registerStoreModules.js'
4import root from 'src/app.vue'
5
6/**
7 * Generate App with pre-fetched data in store state
8 */
9export default function (context) {
10 return new Promise((resolve, reject) => {
11 const { app, router, store } = createApp()
12
13 if (context.req.access_token) app.$cubic.setAccessToken(context.req.access_token)
14 if (context.req.refresh_token) app.$cubic.setRefreshToken(context.req.refresh_token)
15
16 // Init vue-meta
17 const meta = app.$meta()
18
19 // Set router's location
20 router.push(context.req.url)
21
22 // Wait until router has resolved possible async hooks
23 router.onReady(async () => {
24 const routerView = router.getMatchedComponents()
25
26 // Register all dynamic store modules in components first since asyncData
27 // functions will likely depend on them. This also avoids the necessity to
28 // load dependencies first if they're already present in the template.
29
30 // router-view doesn't contain root template, so we call it additionally
31 registerStoreModules(root, store)
32 routerView.map(component => registerStoreModules(component, store))
33
34 // Call asyncData hooks on components matched by the route recursively.
35 // A asyncData hook dispatches a store action and returns a Promise,
36 // which is resolved when the action is complete and store state has been
37 // updated.
38
39 // router-view doesn't contain root template, so we call it additionally
40 await callAsyncRecursive(root, store, router)
41 await Promise.all(routerView.map(component => callAsyncRecursive(component, store, router, router.currentRoute)))
42
43 // After all asyncData hooks are resolved, our store is now
44 // filled with the state needed to render the app.
45 // Expose the state on the render context, and let the request handler
46 // inline the state in the HTML response. This allows the client-side
47 // store to pick-up the server-side state without having to duplicate
48 // the initial data fetching on the client.
49 context.state = store.state
50
51 // Give access token to state so the client can use it
52 if (context.req.access_token) context.state.$access_token = context.req.access_token
53 if (context.req.refresh_token) context.state.$refresh_token = context.req.refresh_token
54
55 // Finally, add meta tags to context for injection in renderer
56 context.meta = { inject: function () { Object.assign(this, meta.inject()) } }
57
58 resolve(app)
59 })
60 })
61}