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.
- package/dist/bin/cli.js +3 -3
- package/dist/bin/dev.js +3 -3
- package/dist/frameworks/vue/fastify-ssr-plugin.js +54 -18
- package/dist/frameworks/vue/prerender.js +4 -4
- package/dist/frameworks/vue/server.js +2 -1
- package/dist/hooks/index.js +1 -0
- package/dist/index.js +16 -5
- package/dist/plugins/index.js +1 -0
- package/dist/plugins/pinia/index.js +60 -0
- package/dist/plugins/quasar/index.js +10 -11
- package/dist/types/frameworks/vue/fastify-ssr-plugin.d.ts +6 -3
- package/dist/types/frameworks/vue/prerender.d.ts +3 -3
- package/dist/types/frameworks/vue/server.d.ts +4 -4
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/plugins/index.d.ts +1 -0
- package/dist/types/plugins/pinia/index.d.ts +5 -0
- package/dist/types/plugins/quasar/index.d.ts +2 -2
- package/dist/types/vitrify-config.d.ts +77 -13
- package/package.json +37 -26
- package/src/node/bin/cli.ts +13 -7
- package/src/node/bin/dev.ts +7 -4
- package/src/node/frameworks/vue/fastify-ssr-plugin.ts +81 -27
- package/src/node/frameworks/vue/prerender.ts +6 -6
- package/src/node/frameworks/vue/server.ts +8 -2
- package/src/node/hooks/index.ts +19 -0
- package/src/node/index.ts +21 -9
- package/src/node/plugins/index.ts +1 -0
- package/src/node/plugins/pinia/index.ts +99 -0
- package/src/node/plugins/quasar/index.ts +17 -19
- package/src/node/vitrify-config.ts +109 -22
- package/src/vite/vue/RootComponent.vue +3 -4
- package/src/vite/vue/main.ts +52 -22
- package/src/vite/vue/ssr/app.ts +3 -2
- package/src/vite/vue/ssr/entry-server.ts +22 -41
- 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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
741
|
+
OnBootHook
|
|
730
742
|
}
|
|
@@ -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
|
-
|
|
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
|
|
36
|
-
ssrContext
|
|
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
|
|
52
|
+
return `${start} ${ssrContext?._meta.htmlAttrs || ''} ${end}`
|
|
53
53
|
})
|
|
54
54
|
.replace(
|
|
55
55
|
/(<head[^>]*)(>)/i,
|
|
56
|
-
(_, start, end) => `${start}${end}${ssrContext
|
|
56
|
+
(_, start, end) => `${start}${end}${ssrContext?._meta.headTags || ''}`
|
|
57
57
|
)
|
|
58
58
|
.replace(
|
|
59
59
|
/(<\/head>)/i,
|
|
60
60
|
(_, tag) =>
|
|
61
|
-
`${ssrContext
|
|
62
|
-
ssrContext
|
|
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
|
|
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
|
|
79
|
-
}${end}${ssrContext
|
|
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
|
|
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
|
-
|
|
207
|
-
|
|
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 {
|
|
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
|
|
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
|
-
|
|
12
|
-
|
|
54
|
+
router,
|
|
55
|
+
ctx,
|
|
56
|
+
initialState,
|
|
57
|
+
ssrContext
|
|
13
58
|
}: {
|
|
14
|
-
app:
|
|
15
|
-
|
|
16
|
-
|
|
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:
|
|
24
|
-
ssrContext:
|
|
79
|
+
app: App
|
|
80
|
+
ssrContext: SSRContext
|
|
25
81
|
staticImports?: Record<string, any>
|
|
26
82
|
}) => Promise<void> | void
|
|
27
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
20
|
-
await fn(instance
|
|
18
|
+
for (let fn of onAppMounted) {
|
|
19
|
+
await fn({ instance })
|
|
21
20
|
}
|
|
22
21
|
})
|
|
23
22
|
|
package/src/vite/vue/main.ts
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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?:
|
|
24
|
+
ssrContext?: SSRContext
|
|
21
25
|
) {
|
|
22
|
-
let
|
|
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)
|
package/src/vite/vue/ssr/app.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
41
|
-
url
|
|
42
|
-
manifest
|
|
43
|
-
ssrContext
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
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(
|
|
44
|
+
const preloadLinks = renderPreloadLinks(ssrContext.modules!, manifest)
|
|
64
45
|
|
|
65
|
-
return
|
|
46
|
+
return { html, preloadLinks, app }
|
|
66
47
|
}
|
|
67
48
|
|
|
68
49
|
function renderPreloadLinks(
|