UNPKG

2.33 kBJavaScriptView Raw
1// eslint-disable-next-line import/no-unresolved
2import createApp from '#out/create-app'
3import ReamError from './ReamError'
4import { routerReady, pageNotFound, runMiddlewares } from './utils'
5import serverHelpers from './server-helpers'
6
7// This exported function will be called by `bundleRenderer`.
8// This is where we perform data-prefetching to determine the
9// state of our application before actually rendering it.
10// Since data fetching is async, this function is expected to
11// return a Promise that resolves to the app instance.
12export default async context => {
13 context.globalState = {}
14 const { req, res } = context
15 const {
16 app,
17 dataStore,
18 router,
19 entry,
20 getInitialDataContextFns,
21 event,
22 middlewares
23 } = createApp(context)
24
25 router.push(req.url)
26
27 await routerReady(router)
28
29 const matchedComponents = router.getMatchedComponents()
30
31 // No matched routes
32 if (matchedComponents.length === 0) {
33 if (res) {
34 res.statusCode = 404
35 context.reamError = pageNotFound(req.url)
36 } else {
37 throw new ReamError({
38 code: 'NOT_FOUND',
39 message: `Cannot find corresponding route component for ${req.url}`
40 })
41 }
42 }
43
44 const dataContext = {
45 req,
46 res,
47 router,
48 route: router.currentRoute,
49 ...serverHelpers
50 }
51
52 for (const fn of getInitialDataContextFns) {
53 fn(dataContext)
54 }
55
56 await runMiddlewares(middlewares, dataContext)
57
58 if (entry.getDocumentData) {
59 const documentData = await entry.getDocumentData(dataContext)
60 context.documentData = Object.assign({}, documentData)
61 }
62
63 await Promise.all(
64 matchedComponents.map(async Component => {
65 const { getInitialData } = Component
66 if (!getInitialData) return
67 const initialData = await getInitialData(dataContext)
68 if (initialData) {
69 for (const key of Object.keys(initialData)) {
70 // `undefined` value will be removed when `JSON.stringify` so we set it to `null` here
71 if (initialData[key] === undefined) {
72 initialData[key] = null
73 }
74 }
75 }
76 dataStore.setData(Component.initialDataKey, initialData)
77 })
78 )
79
80 if (app.$meta) {
81 context.meta = app.$meta()
82 }
83
84 context.globalState.initialData = dataStore.getState()
85
86 event.$emit('before-server-render')
87
88 return app
89}