• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kiva / ui / 15721249898

18 Jun 2025 12:51AM UTC coverage: 52.564% (+4.7%) from 47.872%
15721249898

Pull #6091

github

web-flow
Merge 1f8983303 into e6c7ae52e
Pull Request #6091: feat: cacheable server-side rendering

1789 of 3594 branches covered (49.78%)

Branch coverage included in aggregate %.

276 of 398 new or added lines in 38 files covered. (69.35%)

7 existing lines in 4 files now uncovered.

2629 of 4811 relevant lines covered (54.65%)

280.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/server-app-render.js
1
/* eslint-disable vue/multi-word-component-names, no-throw-literal */
2
import { renderSSRHead } from '@unhead/ssr';
3
import { renderToString } from 'vue/server-renderer';
4
import createApp from '#src/main';
5
import createRouter from '#src/router';
6
import getCDNHeaders from '#src/rendering/cdnHeaders';
7
import fillTemplate from '#src/rendering/fillTemplate';
8
import { renderExternals } from '#src/rendering/externals';
9
import renderGlobals from '#src/rendering/globals';
10
import renderConfigGlobal from '#src/rendering/kvConfig';
11
import { renderPreloadLinks } from '#src/rendering/preloadLinks';
12
import { preFetchAll } from '#src/util/apolloPreFetch';
13
import { authenticationGuard } from '#src/util/authenticationGuard';
14
import setBasketCookie from '#src/util/basketCookie';
15
import logFormatter from '#src/util/logFormatter';
16
import { buildUserDataGlobal } from '#src/util/optimizelyUserMetrics';
17
import setVisitorIdCookie from '#src/util/visitorCookie';
18

NEW
19
const isDev = process.env.NODE_ENV !== 'production';
×
20

21
export default async function renderPage({
22
        cookieStore,
23
        context,
24
        fetch,
25
        kvAuth0,
26
}) {
NEW
27
        const s = isDev && Date.now();
×
28

29
        const {
30
                url,
31
                cdnNotedLoggedIn,
32
                config,
33
                kivaUserAgent,
34
                locale,
35
                device,
36
                ssrManifest,
37
                template,
NEW
38
        } = context;
×
39

40
        // Create a new router instance. This will set the initial route and potentially redirect or 404.
NEW
41
        const router = await createRouter({ isServer: true, url });
×
42

43
        const {
44
                app,
45
                head,
46
                apolloClient,
47
                renderConfig,
NEW
48
        } = await createApp({
×
49
                name: '',
50
                appConfig: config,
51
                apollo: {
52
                        uri: config.graphqlUri,
53
                        types: config.graphqlPossibleTypes
54
                },
55
                cdnNotedLoggedIn,
56
                cookieStore,
57
                device,
58
                kvAuth0,
59
                locale,
60
                fetch,
61
                kivaUserAgent,
62
                router,
63
                isServer: true,
64
        });
65

NEW
66
        try {
×
NEW
67
                if (!renderConfig.useCDNCaching) {
×
68
                        // Set the visitor id cookie
NEW
69
                        setVisitorIdCookie(cookieStore);
×
70

71
                        // Set the basket cookie
NEW
72
                        await setBasketCookie(cookieStore, apolloClient);
×
73
                }
74

75
                // Use route meta property to determine if route needs authentication
76
                // authenticationGuard will reject promise with a redirect to login if
77
                // required authentication query fails
NEW
78
                await authenticationGuard({ route: router.currentRoute.value, apolloClient, kvAuth0 });
×
79

80
                // Pre-fetch graphql queries from the components (and all of their child components)
81
                // matched by the route
82
                // preFetchAll dispatches the queries with Apollo and returns a Promise,
83
                // which is resolved when the action is complete and apollo cache has been updated.
NEW
84
                await preFetchAll(router.currentRoute.value.matched, apolloClient, {
×
85
                        cookieStore,
86
                        kvAuth0,
87
                        route: router.currentRoute.value,
88
                        device,
89
                        renderConfig,
90
                });
91

92
                let sp; // Vue serverPrefetch timing start
NEW
93
                if (isDev) {
×
NEW
94
                        logFormatter(`data pre-fetch: ${Date.now() - s}ms`);
×
NEW
95
                        sp = new Date();
×
96
                }
97

98
                // render the app
NEW
99
                const appHtml = await renderToString(app, context);
×
100

NEW
101
                if (isDev) logFormatter(`vue serverPrefetch: ${Date.now() - sp}ms`);
×
102

103
                // After all preFetch hooks are resolved, our store is now
104
                // filled with the state needed to render the app.
105
                // Expose the state on the render context, and let the request handler
106
                // inline the state in the HTML response. This allows the client-side
107
                // store to pick-up the server-side state without having to duplicate
108
                // the initial data fetching on the client.
NEW
109
                const globals = {
×
110
                        __APOLLO_STATE__: apolloClient.cache.extract(),
111
                };
NEW
112
                if (!router.currentRoute.value.meta?.useCDNCaching) {
×
NEW
113
                        const pageData = buildUserDataGlobal(router.currentRoute.value, cookieStore, apolloClient);
×
NEW
114
                        if (pageData) {
×
NEW
115
                                globals.pageData = pageData;
×
116
                        }
117
                }
NEW
118
                const appState = renderGlobals(globals);
×
119

120
                // render head tags
NEW
121
                const payload = await renderSSRHead(head);
×
122

123
                // render preload links
NEW
124
                const preloadLinks = renderPreloadLinks(context.modules, ssrManifest);
×
125

NEW
126
                const templateData = {
×
127
                        ...payload,
128
                        // Turn off SSR for local development to prevent component FOUC (Flash of Unstyled Content)
129
                        // https://github.com/vitejs/vite/issues/6887#issuecomment-1038664078
130
                        appHtml: isDev ? '' : appHtml,
×
131
                        appState,
132
                        appConfig: renderConfigGlobal(config),
133
                        externals: renderExternals(config),
134
                        googleTagmanagerId: config.googleTagmanagerId,
135
                        preloadLinks,
136
                        // Do not add manifest for local development, as the urls in the manifest do not match their
137
                        // correct location in the vite dev server and cause 404s.
138
                        webManifest: isDev ? '' : '<link rel="manifest" href="/static/manifest.webmanifest">',
×
139
                };
140

NEW
141
                return {
×
142
                        cdnHeaders: getCDNHeaders(renderConfig),
143
                        html: fillTemplate(template, templateData),
144
                        setCookies: cookieStore.getSetCookies(),
145
                };
146
        } catch (error) {
NEW
147
                if (error instanceof Error) {
×
NEW
148
                        throw error;
×
149
                } else {
NEW
150
                        context.setCookies = cookieStore.getSetCookies();
×
NEW
151
                        throw {
×
152
                                url: router.resolve(error).href,
153
                        };
154
                }
155
        }
156
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc