vitrify 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/bin/cli.js +3 -3
  2. package/dist/bin/dev.js +3 -3
  3. package/dist/frameworks/vue/fastify-ssr-plugin.js +54 -18
  4. package/dist/frameworks/vue/prerender.js +4 -4
  5. package/dist/frameworks/vue/server.js +2 -1
  6. package/dist/hooks/index.js +1 -0
  7. package/dist/index.js +16 -5
  8. package/dist/plugins/index.js +1 -0
  9. package/dist/plugins/pinia/index.js +60 -0
  10. package/dist/plugins/quasar/index.js +10 -11
  11. package/dist/types/frameworks/vue/fastify-ssr-plugin.d.ts +6 -3
  12. package/dist/types/frameworks/vue/prerender.d.ts +3 -3
  13. package/dist/types/frameworks/vue/server.d.ts +4 -4
  14. package/dist/types/hooks/index.d.ts +2 -0
  15. package/dist/types/index.d.ts +2 -2
  16. package/dist/types/plugins/index.d.ts +1 -0
  17. package/dist/types/plugins/pinia/index.d.ts +5 -0
  18. package/dist/types/plugins/quasar/index.d.ts +2 -2
  19. package/dist/types/vitrify-config.d.ts +77 -13
  20. package/package.json +37 -26
  21. package/src/node/bin/cli.ts +13 -7
  22. package/src/node/bin/dev.ts +7 -4
  23. package/src/node/frameworks/vue/fastify-ssr-plugin.ts +81 -27
  24. package/src/node/frameworks/vue/prerender.ts +6 -6
  25. package/src/node/frameworks/vue/server.ts +8 -2
  26. package/src/node/hooks/index.ts +19 -0
  27. package/src/node/index.ts +21 -9
  28. package/src/node/plugins/index.ts +1 -0
  29. package/src/node/plugins/pinia/index.ts +99 -0
  30. package/src/node/plugins/quasar/index.ts +17 -19
  31. package/src/node/vitrify-config.ts +109 -22
  32. package/src/vite/vue/RootComponent.vue +3 -4
  33. package/src/vite/vue/main.ts +52 -22
  34. package/src/vite/vue/ssr/app.ts +3 -2
  35. package/src/vite/vue/ssr/entry-server.ts +22 -41
  36. package/src/vite/vue/ssr/prerender.ts +2 -2
package/src/node/index.ts CHANGED
@@ -17,8 +17,7 @@ import { visualizer } from 'rollup-plugin-visualizer'
17
17
  import { fileURLToPath } from 'url'
18
18
  import type {
19
19
  StaticImports,
20
- BootFunction,
21
- OnMountedHook,
20
+ OnAppMountedHook,
22
21
  VitrifyConfig,
23
22
  VitrifyConfigAsync,
24
23
  VitrifyCommands,
@@ -27,7 +26,9 @@ import type {
27
26
  VitrifySSRModes,
28
27
  OnRenderedHook,
29
28
  OnBootHook,
30
- OnSetupFile
29
+ OnSetupFile,
30
+ onAppCreatedHook,
31
+ OnTemplateRenderedHook
31
32
  } from './vitrify-config.js'
32
33
  import type { VitrifyContext } from './bin/run.js'
33
34
  import type { VitrifyPlugin } from './plugins/index.js'
@@ -63,7 +64,7 @@ const manualChunkNames = [
63
64
  ]
64
65
 
65
66
  const moduleChunks = {
66
- vue: ['vue', '@vue', 'vue-router'],
67
+ vue: ['vue', '@vue', 'vue-router', 'pinia', '@pinia/colada', '@vue/devtools'],
67
68
  quasar: ['quasar'],
68
69
  atQuasar: ['@quasar']
69
70
  }
@@ -279,7 +280,9 @@ export const baseConfig = async ({
279
280
 
280
281
  let onBootHooks: OnBootHook[]
281
282
  let onRenderedHooks: OnRenderedHook[]
282
- let onMountedHooks: OnMountedHook[]
283
+ let onTemplateRenderedHooks: OnTemplateRenderedHook[]
284
+ let onAppMountedHooks: OnAppMountedHook[]
285
+ let onAppCreatedHooks: onAppCreatedHook[]
283
286
  let onSetupFiles: OnSetupFile[]
284
287
  let globalCss: string[] = []
285
288
  let staticImports: StaticImports
@@ -357,7 +360,10 @@ export const baseConfig = async ({
357
360
  config: (config: VitrifyConfig, env) => {
358
361
  onBootHooks = config.vitrify?.hooks?.onBoot || []
359
362
  onRenderedHooks = config.vitrify?.hooks?.onRendered || []
360
- onMountedHooks = config.vitrify?.hooks?.onMounted || []
363
+ onTemplateRenderedHooks =
364
+ config.vitrify?.hooks?.onTemplateRendered || []
365
+ onAppMountedHooks = config.vitrify?.hooks?.onAppMounted || []
366
+ onAppCreatedHooks = config.vitrify?.hooks?.onAppCreated || []
361
367
  onSetupFiles = config?.vitrify?.hooks?.onSetup || []
362
368
  globalCss = config.vitrify?.globalCss || []
363
369
  staticImports = config.vitrify?.staticImports || {}
@@ -389,12 +395,18 @@ export const baseConfig = async ({
389
395
  return `export const onBoot = [${onBootHooks
390
396
  .map((fn) => `${String(fn)}`)
391
397
  .join(', ')}]
392
- export const onMounted = [${onMountedHooks
398
+ export const onAppMounted = [${onAppMountedHooks
393
399
  .map((fn) => `${String(fn)}`)
394
400
  .join(', ')}]
395
401
  export const onRendered = [${onRenderedHooks
396
402
  .map((fn) => `${String(fn)}`)
397
403
  .join(', ')}]
404
+ export const onTemplateRendered = [${onTemplateRenderedHooks
405
+ .map((fn) => `${String(fn)}`)
406
+ .join(', ')}]
407
+ export const onAppCreated = [${onAppCreatedHooks
408
+ .map((fn) => `${String(fn)}`)
409
+ .join(', ')}]
398
410
  export const onSetup = []
399
411
  ${onSetupFiles
400
412
  .map((url, index) => {
@@ -676,7 +688,7 @@ export const baseConfig = async ({
676
688
  alias
677
689
  },
678
690
  build: {
679
- target: ssr === 'server' || ssr === 'fastify' ? 'esnext' : 'modules',
691
+ target: 'esnext',
680
692
  ssr: ssr === 'server' || ssr === 'fastify' ? true : false,
681
693
  ssrManifest: ssr === 'client' || ssr === 'ssg',
682
694
  rollupOptions
@@ -726,5 +738,5 @@ export type {
726
738
  VitrifyConfigAsync,
727
739
  VitrifyPlugin,
728
740
  VitrifyContext,
729
- BootFunction
741
+ OnBootHook
730
742
  }
@@ -26,3 +26,4 @@ export type VitrifyPlugin<Options> = ({
26
26
  }) => Promise<VitrifyPluginReturnType> | VitrifyPluginReturnType
27
27
 
28
28
  export * from './quasar/index.js'
29
+ export * from './pinia/index.js'
@@ -0,0 +1,99 @@
1
+ import type { onAppCreatedHook, OnRenderedHook } from '../../vitrify-config.js'
2
+ import type { VitrifyPlugin } from '../index.js'
3
+
4
+ export type PiniaPluginOptions = {
5
+ // Initialize Pinia Colada
6
+ colada?: boolean
7
+ }
8
+
9
+ const piniaOnAppCreated: onAppCreatedHook = async ({
10
+ app,
11
+ ctx,
12
+ initialState,
13
+ ssrContext
14
+ }) => {
15
+ const { createPinia } = await import('pinia')
16
+ const pinia = createPinia()
17
+ ctx.pinia = pinia
18
+ app.use(pinia)
19
+
20
+ // SSR Client
21
+ if (initialState?.pinia) pinia.state.value = initialState.pinia
22
+ // SSR Server
23
+ if (ssrContext) ssrContext.pinia = pinia
24
+ }
25
+
26
+ const piniaOnRenderedHook: OnRenderedHook = async ({ app, ssrContext }) => {
27
+ // SSR Server
28
+ if (ssrContext?.initialState && ssrContext.pinia) {
29
+ ssrContext.initialState.pinia = ssrContext.pinia.state.value
30
+ }
31
+ }
32
+
33
+ const piniaColadaonAppCreated: onAppCreatedHook = async ({
34
+ app,
35
+ ctx,
36
+ initialState
37
+ }) => {
38
+ if (ctx.pinia) {
39
+ const { PiniaColada, hydrateQueryCache, useQueryCache } = await import(
40
+ '@pinia/colada'
41
+ )
42
+ app.use(PiniaColada)
43
+
44
+ if (initialState?.piniaColada) {
45
+ app.runWithContext(() =>
46
+ hydrateQueryCache(
47
+ useQueryCache(ctx.pinia),
48
+ initialState.piniaColada || {}
49
+ )
50
+ )
51
+ }
52
+ }
53
+ }
54
+
55
+ const piniaColadaOnRenderedHook: OnRenderedHook = async ({
56
+ app,
57
+ ssrContext
58
+ }) => {
59
+ // SSR Server
60
+ if (ssrContext?.initialState && ssrContext.pinia) {
61
+ const { useQueryCache, serializeQueryCache } = await import('@pinia/colada')
62
+
63
+ // Delete to prevent Non-POJO error
64
+ if (ssrContext.initialState.pinia?._pc_query) {
65
+ delete ssrContext.initialState.pinia._pc_query
66
+ }
67
+ ssrContext.initialState.piniaColada = app.runWithContext(() =>
68
+ serializeQueryCache(useQueryCache())
69
+ )
70
+ }
71
+ }
72
+
73
+ export const PiniaPlugin: VitrifyPlugin<PiniaPluginOptions> = async ({
74
+ ssr = false,
75
+ pwa = false,
76
+ options = {}
77
+ }) => {
78
+ const onAppCreated = [piniaOnAppCreated]
79
+ const onRendered = [piniaOnRenderedHook]
80
+ if (options.colada) {
81
+ onAppCreated.push(piniaColadaonAppCreated)
82
+ onRendered.push(piniaColadaOnRenderedHook)
83
+ }
84
+
85
+ return {
86
+ plugins: [],
87
+ config: {
88
+ vitrify: {
89
+ ssr: {
90
+ serverModules: ['@pinia/colada']
91
+ },
92
+ hooks: {
93
+ onAppCreated,
94
+ onRendered
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
@@ -1,8 +1,8 @@
1
- import type { Plugin } from 'vite'
2
1
  import { fileURLToPath } from 'url'
3
2
  import type {
4
3
  OnBootHook,
5
- OnMountedHook,
4
+ OnAppMountedHook,
5
+ OnTemplateRenderedHook,
6
6
  VitrifyConfig
7
7
  } from '../../vitrify-config.js'
8
8
  import type { VitrifyPlugin } from '../index.js'
@@ -31,10 +31,10 @@ export interface QuasarPluginOptions {
31
31
  disableSass?: boolean
32
32
  }
33
33
 
34
- export const injectSsrContext = (
35
- html: string,
36
- ssrContext: Record<string, any>
37
- ) =>
34
+ export const injectSsrContext: OnTemplateRenderedHook = ({
35
+ html,
36
+ ssrContext
37
+ }) =>
38
38
  html
39
39
  .replace(/(<html[^>]*)(>)/i, (found, start, end) => {
40
40
  let matches
@@ -49,21 +49,21 @@ export const injectSsrContext = (
49
49
  start = start.replace(matches[0], '')
50
50
  }
51
51
 
52
- return `${start} ${ssrContext._meta.htmlAttrs || ''} ${end}`
52
+ return `${start} ${ssrContext?._meta.htmlAttrs || ''} ${end}`
53
53
  })
54
54
  .replace(
55
55
  /(<head[^>]*)(>)/i,
56
- (_, start, end) => `${start}${end}${ssrContext._meta.headTags || ''}`
56
+ (_, start, end) => `${start}${end}${ssrContext?._meta.headTags || ''}`
57
57
  )
58
58
  .replace(
59
59
  /(<\/head>)/i,
60
60
  (_, tag) =>
61
- `${ssrContext._meta.resourceStyles || ''}${
62
- ssrContext._meta.endingHeadTags || ''
61
+ `${ssrContext?._meta.resourceStyles || ''}${
62
+ ssrContext?._meta.endingHeadTags || ''
63
63
  }${tag}`
64
64
  )
65
65
  .replace(/(<body[^>]*)(>)/i, (found, start, end) => {
66
- let classes = ssrContext._meta.bodyClasses || ''
66
+ let classes = ssrContext?._meta.bodyClasses || ''
67
67
 
68
68
  const matches = found.match(/\sclass\s*=\s*['"]([^'"]*)['"]/i)
69
69
 
@@ -75,8 +75,8 @@ export const injectSsrContext = (
75
75
  }
76
76
 
77
77
  return `${start} class="${classes.trim()}" ${
78
- ssrContext._meta.bodyAttrs || ''
79
- }${end}${ssrContext._meta.bodyTags || ''}`
78
+ ssrContext?._meta.bodyAttrs || ''
79
+ }${end}${ssrContext?._meta.bodyTags || ''}`
80
80
  })
81
81
 
82
82
  export const QuasarPlugin: VitrifyPlugin<QuasarPluginOptions> = async ({
@@ -136,8 +136,8 @@ export const QuasarPlugin: VitrifyPlugin<QuasarPluginOptions> = async ({
136
136
  }
137
137
  })()
138
138
 
139
- const onMountedHooks: OnMountedHook[] = [
140
- async (instance) => {
139
+ const onAppMountedHooks: OnAppMountedHook[] = [
140
+ async ({ instance }) => {
141
141
  const {
142
142
  proxy: { $q }
143
143
  } = instance
@@ -203,8 +203,8 @@ export const QuasarPlugin: VitrifyPlugin<QuasarPluginOptions> = async ({
203
203
  },
204
204
  hooks: {
205
205
  onBoot: onBootHooks,
206
- onMounted: onMountedHooks,
207
- onRendered: [injectSsrContext]
206
+ onAppMounted: onAppMountedHooks,
207
+ onTemplateRendered: [injectSsrContext]
208
208
  },
209
209
  sass: quasarConf.disableSass
210
210
  ? undefined
@@ -316,5 +316,3 @@ export const QuasarPlugin: VitrifyPlugin<QuasarPluginOptions> = async ({
316
316
  }
317
317
  }
318
318
  }
319
-
320
- export default QuasarPlugin
@@ -1,48 +1,127 @@
1
1
  import type { Alias, UserConfig as ViteUserConfig, ViteDevServer } from 'vite'
2
2
  import type { ComponentInternalInstance } from '@vue/runtime-core'
3
- import type { FastifyInstance, FastifyServerOptions } from 'fastify'
3
+ import type {
4
+ FastifyInstance,
5
+ FastifyReply,
6
+ FastifyRequest,
7
+ FastifyServerOptions
8
+ } from 'fastify'
4
9
  import type { VitePWAOptions } from 'vite-plugin-pwa'
5
10
  import type { Options as unpluginVueComponentsOptions } from 'unplugin-vue-components'
6
11
  import type { UserConfig as UnoCSSUserConfig } from '@unocss/core'
7
- import { VitrifyPlugin } from './plugins/index.js'
12
+ import type { VitrifyPlugin } from './plugins/index.js'
13
+ import type { Router } from 'vue-router'
14
+ import type { App } from '@vue/runtime-core'
15
+ import type { Pinia } from 'pinia'
16
+ import type { _UseQueryEntryNodeValueSerialized } from '@pinia/colada/index.js'
8
17
 
9
- export type BootFunction = ({
18
+ export type SSRContext = {
19
+ // Quasar requires req and res on SSRContext instead of request and reply
20
+ req:
21
+ | FastifyRequest
22
+ | {
23
+ headers: Record<string, unknown>
24
+ url: string
25
+ }
26
+ res: FastifyReply | Record<string, unknown>
27
+ provide: Record<string, unknown>
28
+ initialState: {
29
+ provide?: Record<string, unknown>
30
+ pinia?: Record<string, unknown>
31
+ piniaColada?: Record<string, _UseQueryEntryNodeValueSerialized>
32
+ [key: string]: unknown
33
+ }
34
+ pinia?: Pinia
35
+ // Quasar internals
36
+ _modules: Set<unknown>
37
+ _meta: Record<string, any>
38
+ __qMetaList: unknown[]
39
+ /**
40
+ * Required for Quasar
41
+ */
42
+ onRenderedList: (() => unknown)[]
43
+ onRendered: (fn: () => unknown) => void
44
+ /**
45
+ * Vue internals
46
+ */
47
+ modules?: Map<unknown, unknown>
48
+ transports?: Record<string, unknown>
49
+ [key: string]: unknown
50
+ }
51
+
52
+ export type onAppCreatedHook = ({
10
53
  app,
11
- ssrContext,
12
- staticImports
54
+ router,
55
+ ctx,
56
+ initialState,
57
+ ssrContext
13
58
  }: {
14
- app: any
15
- ssrContext: Record<string, unknown>
16
- staticImports: Record<string, any>
59
+ app: App
60
+ router: Router
61
+ ctx: {
62
+ pinia?: Pinia
63
+ [key: string]: unknown
64
+ }
65
+ initialState: {
66
+ provide?: Record<string, unknown>
67
+ pinia?: Record<string, unknown>
68
+ piniaColada?: Record<string, _UseQueryEntryNodeValueSerialized>
69
+ [key: string]: unknown
70
+ }
71
+ ssrContext?: SSRContext
17
72
  }) => Promise<void> | void
73
+
18
74
  export type OnBootHook = ({
19
75
  app,
20
76
  ssrContext,
21
77
  staticImports
22
78
  }: {
23
- app: any
24
- ssrContext: Record<string, unknown>
79
+ app: App
80
+ ssrContext: SSRContext
25
81
  staticImports?: Record<string, any>
26
82
  }) => Promise<void> | void
27
- export type OnMountedHook = (
83
+
84
+ export type OnAppMountedHook = ({
85
+ instance
86
+ }: {
28
87
  instance: ComponentInternalInstance
29
- ) => Promise<void> | void
88
+ }) => Promise<void> | void
30
89
  export type StaticImports = Record<string, string[]>
31
- export type SsrFunction = (
32
- html: string,
33
- ssrContext: Record<string, any>
34
- ) => string
35
- export type OnRenderedHook = (
36
- html: string,
37
- ssrContext: Record<string, any>
38
- ) => string
90
+
91
+ export type OnSetupFile = URL
39
92
  export type OnSetupHook = (
40
93
  fastify: FastifyInstance,
41
94
  options?: {
42
95
  vite?: ViteDevServer
43
96
  }
44
97
  ) => any
45
- export type OnSetupFile = URL
98
+
99
+ export type Render = (
100
+ url: string,
101
+ manifest: Record<string, unknown>,
102
+ ssrContext: SSRContext,
103
+ renderToString: (app: App, ctx?: Record<string, any>) => Promise<string>
104
+ ) => Promise<{
105
+ html: string
106
+ preloadLinks: string
107
+ app: App
108
+ }>
109
+
110
+ export type OnRenderedHook = ({
111
+ app,
112
+ ssrContext
113
+ }: {
114
+ app: App
115
+ ssrContext?: SSRContext
116
+ }) => Promise<void> | void
117
+
118
+ export type OnTemplateRenderedHook = ({
119
+ html,
120
+ ssrContext
121
+ }: {
122
+ html: string
123
+ ssrContext?: SSRContext
124
+ }) => Promise<string> | string
46
125
 
47
126
  export interface VitrifyConfig extends ViteUserConfig {
48
127
  vitrify?: {
@@ -67,7 +146,7 @@ export interface VitrifyConfig extends ViteUserConfig {
67
146
  /**
68
147
  * Functions which run in the onMounted hook of the app
69
148
  */
70
- onMounted?: OnMountedHook[]
149
+ onAppMounted?: OnAppMountedHook[]
71
150
  /**
72
151
  * Functions which run after initializing the app
73
152
  */
@@ -76,6 +155,14 @@ export interface VitrifyConfig extends ViteUserConfig {
76
155
  * Functions which run after rendering the app (SSR)
77
156
  */
78
157
  onRendered?: OnRenderedHook[]
158
+ /**
159
+ * Functions which run after rendering the template (SSR)
160
+ */
161
+ onTemplateRendered?: OnTemplateRenderedHook[]
162
+ /**
163
+ * Functions which run directly after initializing the application
164
+ */
165
+ onAppCreated?: onAppCreatedHook[]
79
166
  }
80
167
  /**
81
168
  * Global SASS variables
@@ -8,16 +8,15 @@ import {
8
8
  onMounted as onMountedVue,
9
9
  getCurrentInstance
10
10
  } from 'vue'
11
- import { onBoot, onMounted } from 'virtual:vitrify-hooks'
12
- import * as staticImports from 'virtual:static-imports'
11
+ import { onAppMounted } from 'virtual:vitrify-hooks'
13
12
  import App from 'src/App.vue'
14
13
  // import 'vitrify.sass'
15
14
  const instance = getCurrentInstance()
16
15
  const props = defineProps()
17
16
 
18
17
  onMountedVue(async () => {
19
- for (let fn of onMounted) {
20
- await fn(instance, staticImports)
18
+ for (let fn of onAppMounted) {
19
+ await fn({ instance })
21
20
  }
22
21
  })
23
22
 
@@ -1,14 +1,18 @@
1
1
  import createRouter from 'src/router'
2
- import { createSSRApp, createApp as createVueApp, ref } from 'vue'
3
- import { onBoot } from 'virtual:vitrify-hooks'
2
+ import { App, createSSRApp, createApp as createVueApp, ref } from 'vue'
3
+ import { onBoot, onAppCreated } from 'virtual:vitrify-hooks'
4
4
  import routes from 'src/router/routes'
5
5
  import * as staticImports from 'virtual:static-imports'
6
6
  import 'virtual:uno.css'
7
-
8
7
  import RootComponent from './RootComponent.vue'
9
- interface ssrContext {
10
- provide?: Record<string, unknown>
11
- [key: string]: unknown
8
+ import { parse } from 'devalue'
9
+ import type { SSRContext } from '../../node/vitrify-config'
10
+ import type { Pinia } from 'pinia'
11
+
12
+ declare global {
13
+ interface Window {
14
+ __INITIAL_STATE__: any
15
+ }
12
16
  }
13
17
 
14
18
  function capitalizeFirstLetter(string: string) {
@@ -17,18 +21,58 @@ function capitalizeFirstLetter(string: string) {
17
21
 
18
22
  export async function createApp(
19
23
  ssr?: 'client' | 'server',
20
- ssrContext?: ssrContext
24
+ ssrContext?: SSRContext
21
25
  ) {
22
- let app
26
+ let initialState: Record<string, any> | null = null
27
+
28
+ if (!import.meta.env.SSR && window?.__INITIAL_STATE__) {
29
+ initialState = window.__INITIAL_STATE__
30
+
31
+ for (const key in initialState) {
32
+ if (key === 'provide' || key === 'piniaColada') {
33
+ initialState[key] = JSON.parse(initialState[key])
34
+ } else {
35
+ initialState[key] = parse(initialState[key], {
36
+ PiniaColada_TreeMapNode: (data) => data
37
+ })
38
+ }
39
+ }
40
+ }
41
+
42
+ // Delete for security reasons
43
+ if (!import.meta.env.SSR && window.__INITIAL_STATE__)
44
+ delete window.__INITIAL_STATE__
45
+
46
+ let provide: Record<string, any> = {}
47
+ if (import.meta.env.SSR) {
48
+ if (ssrContext?.provide) {
49
+ provide = ssrContext?.provide
50
+ }
51
+ } else {
52
+ if (initialState) {
53
+ provide = initialState.provide
54
+ }
55
+ }
56
+
57
+ let app: App
58
+ const ctx: {
59
+ pinia?: Pinia
60
+ [key: string]: unknown
61
+ } = {}
23
62
 
24
63
  if (ssr) {
25
64
  app = createSSRApp(RootComponent)
26
65
  } else {
27
66
  app = createVueApp(RootComponent)
28
67
  }
68
+
29
69
  const router = createRouter()
30
70
  app.use(router)
31
71
 
72
+ for (const fn of onAppCreated) {
73
+ await fn({ app, router, ctx, initialState, ssrContext })
74
+ }
75
+
32
76
  // Workaround to fix hydration errors when serving html files directly
33
77
  router.beforeEach((to, from, next) => {
34
78
  if (to.path.endsWith('.html')) {
@@ -38,20 +82,6 @@ export async function createApp(
38
82
  next()
39
83
  })
40
84
 
41
- let initialState: Record<string, any>
42
- let provide: Record<string, any> = {}
43
- if (import.meta.env.SSR) {
44
- if (ssrContext?.provide) {
45
- provide = ssrContext?.provide
46
- }
47
- } else {
48
- // @ts-expect-error undefined
49
- if (window.__INITIAL_STATE__) {
50
- // @ts-expect-error undefined
51
- initialState = JSON.parse(window.__INITIAL_STATE__)
52
- provide = initialState.provide
53
- }
54
- }
55
85
  for (const key in provide) {
56
86
  if (provide[key]?.value) {
57
87
  const refValue = ref(provide[key].value)
@@ -1,6 +1,6 @@
1
1
  import { createApp } from '../../../node/frameworks/vue/server.js'
2
2
  import { getAppDir } from '../../../node/app-urls.js'
3
- import { onSetup, onRendered } from 'virtual:vitrify-hooks'
3
+ import { onSetup, onRendered, onTemplateRendered } from 'virtual:vitrify-hooks'
4
4
  import { fastifySsrPlugin } from './fastify-ssr-plugin.js'
5
5
 
6
6
  const getString = (str?: string) => str
@@ -14,9 +14,10 @@ export const setupApp = async () => {
14
14
  baseUrl,
15
15
  fastifyPlugin: fastifySsrPlugin,
16
16
  onRendered,
17
+ onTemplateRendered,
17
18
  mode: import.meta.env.MODE
18
19
  })
19
20
  }
20
21
 
21
22
  export { default as vitrifyConfig } from 'virtual:vitrify-config'
22
- export { onRendered }
23
+ export { onRendered, onTemplateRendered }
@@ -1,28 +1,10 @@
1
- import { type FastifyReply, type FastifyRequest } from 'fastify'
2
1
  import { createApp } from '../main.js'
3
- import { renderToString as renderToStringVue } from 'vue/server-renderer'
4
-
5
- const initializeApp = async (
6
- url: string,
7
- ssrContext: Record<string, unknown>
8
- ) => {
9
- const onRenderedList: (() => unknown)[] = []
10
- Object.assign(ssrContext, {
11
- _modules: new Set(),
12
- _meta: {},
13
- onRendered: (fn: () => unknown) => {
14
- onRenderedList.push(fn)
15
- }
16
- })
2
+ import type { Render, SSRContext } from '../../../node/vitrify-config.js'
17
3
 
4
+ const initializeApp = async (url: string, ssrContext: SSRContext) => {
18
5
  const { app, router, routes } = await createApp('server', ssrContext)
19
6
 
20
7
  router.push({ path: url })
21
- ssrContext.initialState = {}
22
-
23
- onRenderedList.forEach((fn) => {
24
- fn()
25
- })
26
8
 
27
9
  await router.isReady()
28
10
 
@@ -33,36 +15,35 @@ export const getRoutes = async () =>
33
15
  (
34
16
  await initializeApp('/', {
35
17
  req: { headers: {}, url: '/' },
36
- res: {}
18
+ res: {},
19
+ provide: {},
20
+ initialState: {},
21
+ onTemplateRenderedInternal: [],
22
+ _modules: new Set(),
23
+ _meta: {},
24
+ __qMetaList: [],
25
+ onRenderedList: [],
26
+ onRendered: (fn: () => unknown) => {
27
+ return
28
+ }
37
29
  })
38
30
  ).routes
39
31
 
40
- export async function render(
41
- url: string,
42
- manifest: Record<string, unknown>,
43
- ssrContext: {
44
- request: FastifyRequest | { headers: Record<string, unknown>; url: string }
45
- reply: FastifyReply | Record<string, unknown>
46
- provide: Record<string, unknown>
47
- },
48
- renderToString: typeof renderToStringVue
49
- ) {
32
+ export const render: Render = async (
33
+ url,
34
+ manifest,
35
+ ssrContext,
36
+ renderToString
37
+ ) => {
50
38
  if (!renderToString)
51
39
  renderToString = (await import('vue/server-renderer')).renderToString
52
40
  const { app, router } = await initializeApp(url, ssrContext)
53
41
 
54
- const ctx: {
55
- modules?: Map<unknown, unknown>
56
- transports?: Record<string, unknown>
57
- __qMetaList: unknown[]
58
- } = {
59
- __qMetaList: []
60
- }
61
- const html = await renderToString(app, ctx)
42
+ const html = await renderToString(app, ssrContext)
62
43
 
63
- const preloadLinks = renderPreloadLinks(ctx.modules!, manifest)
44
+ const preloadLinks = renderPreloadLinks(ssrContext.modules!, manifest)
64
45
 
65
- return [html, preloadLinks]
46
+ return { html, preloadLinks, app }
66
47
  }
67
48
 
68
49
  function renderPreloadLinks(